Circular View path error Spring boot
Asked Answered
E

12

48

I am very new to Spring. I am trying to build a MVC application using Spring Boot which shows a list of products. But i am getting the below error:

javax.servlet.ServletException: Circular view path [products]: would dispatch back to the current handler URL [/products] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)

Here is controller:

package com.springframeworkguru.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springframeworkguru.services.ProductService;


    @Controller
    public class ProductController {

        private ProductService productService;

        @Autowired
        public void setProductService(ProductService productService) {
            this.productService = productService;
        }

        @RequestMapping("/products")
        public String listProducts(Model model){

            model.addAttribute("products", productService.listAllProducts());

            return "products";
        }

    }

This is the main class:

package com.springframeworkguru;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

import com.springframeworkguru.controllers.ProductController;

@SpringBootApplication
public class SpringmvcApplication extends SpringBootServletInitializer{

     public static void main(String[] args) {
        SpringApplication.run(SpringmvcApplication.class, args);
    }
}

and products.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Spring Core Online Tutorial - List Products</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

    <link href="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.4/css/bootstrap.min.css"
          th:href="@{/webjars/bootstrap/3.3.5/css/bootstrap.min.css}"
          rel="stylesheet" media="screen"/>

    <script src="http://cdn.jsdelivr.net/webjars/jquery/2.1.4/jquery.min.js"
            th:src="@{/webjars/jquery/2.1.4/jquery.min.js}"></script>

    <link href="../css/spring-core.css"
          th:href="@{css/spring-core.css}" rel="stylesheet" media="screen"/>
</head>
<body>
<div class="container">
    <div th:if="${not #lists.isEmpty(products)}">
        <h2>Product List</h2>
        <table class="table table-striped">
            <tr>
                <th>Id</th>
                <th>Description</th>
                <th>Price</th>
                <th>Image URL</th>
                <th>List</th>
            </tr>
            <tr th:each="product : ${products}">
                <td th:text="${product.id}"></td>
                <td th:text="${product.description}"></td>
                <td th:text="${product.price}"></td>
                <td th:text="${product.imageUrl}"></td>
                <td><a th:href="${'/product/' + product.id}">View</a> </td>
            </tr>
        </table>
    </div>
</div>

</body>
</html>

The products.html is in /static folder. Also, I am using Eclipse Kepler.

Encyclical answered 18/4, 2016 at 15:0 Comment(0)
O
131

Adding spring-boot-starter-thymeleaf dependency solved the problem.

So add this to your pom.xml file:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Update: If you are working with Eclipse and you are using Gradle, this might not work. The reason is if you haven't imported the project as 'gradle project' Eclipse wont detect thymeleaf. So here's the solution:

Step1 : Run "gradle eclipse" on command line.

Step2 : Run "gradle wrapper"

Step3 : In eclipse import as gradle project (before this remove the already imported project)

Step4 : Now run using eclipse

Step5 : Enjoy!

Oneal answered 29/1, 2017 at 7:20 Comment(3)
Wow! This really did solve my problem. It seems so silly to miss a dependency and get a completely different error message. The error message is also very deceiving.Gazelle
This worked for me. However, if using IntelliJ IDEA and maven, then just adding this dependency to your pom.xml may not be sufficient. In my case, I needed to also then go to: View > Tool Windows > Maven, then click "Reload all Maven Projects". Only after that did my project find spring-boot-starter-thymeleaf and then the run time "Circular view path..." error was resolved.Pinniped
The same is true for IntelliJ IDEA and Gradle. You may need to also View > Tool Windows > Gradle, then click "Reload all Gradle Projects".Jeopardous
N
41

You can also be here because:

  1. You forgot to put the @RestController of your rest controller over the class

  2. You set @Controller instead of @RestController

Nd answered 23/7, 2019 at 13:59 Comment(7)
+^ Thanks! This did the trick. I had put the @Controller and that didn't work, but adding @RestController made the circular dependency issue go away!Bilbo
Thanks for the tip, for me it was a @ResponseBody. Better watch these annotations.Change
This worked for me. As @Bilbo noted, I, too, was using @Controller instead of @RestControllerEuchromosome
Can anyone explain why @RestController working instead of @Controller ??Cyprio
@ RestController = @ Controller + @ ResponseBody. So if you put @Controller, in short, it is assumed that you will use the presentation (jsp, html, thymeleaf) and it should be configured for you. The error occurs due to the lack of settings for the presentation.Nd
@S.Dayneko I just had the same situation with replacing @Controller with @RestController and it worked fine, then came across your comment, it was really informative comment. I know I'm a bit late to this discussion. But, would you please tell me if @RestController would still work fine with thymeleaf because I was following a guide and they were using @Controller, especially I don't want to loose the auto mapping feature for the template directory that thymeleaf provide. Again, sorry for I'm bit late.Leonidaleonidas
Thanks - saved me a bunch of time hereUtile
U
14

The products.html is /static folder

By default, Spring Boot will look for Thymeleaf templates in templates directory on the classpath. So move your products.html to src/main/resources/templates directory. You can read more about template engines and Spring Boot on the Spring Boot Documentation:

When you’re using thymeleaf templating engine with the default configuration, your templates will be picked up automatically from src/main/resources/templates

Also, static directory is where you should put your Static Contents, not your templates.

Unsphere answered 18/4, 2016 at 15:20 Comment(4)
i have done that. But the same error - javax.servlet.ServletException: Circular view path [products]: would dispatch back to the current handler URL [/products] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.). 2016-04-19 00:01:35.129 ERROR 3200 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet dispatcherServlet threw exceptionEncyclical
Did you add the spring-boot-starter-thymeleaf dependency?Unsphere
Thanks a lot. It worked after adding spring-boot-starter-thymeleaf, spring-boot-starter-web dependency.Encyclical
Thanks, It also worked after adding spring-boot-starter-thymeleaf and spring-boot-starter-web.Kerrison
S
13

Add the following dependency in pom.xml

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>1.4.0.RELEASE</version>
</dependency>

The latest version could be found on mvnrepository

Shook answered 22/6, 2017 at 3:45 Comment(1)
When you specify a version for Thymeleaf be careful not to override the managed version for SpringBoot! This can sometimes cause problems.Bullring
B
7

Well I had the same problem using SpringBoot and all I did was replacing @Controller with @RestController and it worked fine.

Bibliolatry answered 19/10, 2019 at 16:52 Comment(0)
E
4

Convert @Controller to @RestController, this will fix the circular path problem.

Emanation answered 14/8, 2020 at 4:40 Comment(0)
O
4

By default, Spring Boot uses the InternalResourceView class as the view resolver. If the @GetMapping value is the same as the view name, the request fails with the circular view path error.

So one solution is to not to use the same name for a URL path and view name.

If we choose a Thymeleaf processor, the error is not there.

I had an example with Freemarker and had the circular view path error (Spring Boot 2.2.4). I had to rename the URL path.

Orndorff answered 10/9, 2020 at 7:21 Comment(0)
V
2

Problems can be caused by using an embedded servlet container (embedded tomcat). @mirmdasif answer

To resolve this use external tomcat server.

Configure tomcat server in STS/Eclipse:
1. from top menu: Window > Show View > Servers
2. in servers tab window context menu: New > Server
3. do project config to deploy WAR file to Tomcat.
4. run project as Spring Boot App

deploy WAR file to Tomcat
Main class should exteneds SpringBootServletInitializer and override SpringApplicationBuilder method...

package package_with_your_main_class;

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 YourStartWebApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(YourStartWebApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(YourStartWebApplication.class);
    }
}

pom.xml should contains

<!-- Parent pom providing dependency and plugin management for applications -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <!-- this version works with tomcat 8.5, change to newest if you are using newer tomcat -->
    <version>2.0.9.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <java.version>1.8</java.version>
    <!-- The main class to start by executing java -jar -->
    <start-class>package_with_your_main_class.SpringBootWebApplication</start-class>
</properties>

<dependencies>
    <!-- springframework web starter module -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- templating language -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId> 
    </dependency>

    <!-- marked the embedded servlet container as provided -->
    <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>

<packaging>war</packaging>
Vrablik answered 20/9, 2019 at 10:57 Comment(0)
F
2

make sure you have enabled thymeleaf with spring in application.properties :

spring.thymeleaf.enabled=true

Flytrap answered 12/12, 2019 at 20:51 Comment(0)
F
2

For springboot 2.6.0, try @RestController to the class or @ResponseBody to the method.

e.g.

import org.springframework.web.bind.annotation.RestController;

...

@RestController
public class ProductController {

   private ProductService productService;

   @Autowired
   public void setProductService(ProductService productService) {
       this.productService = productService;
   }

   @RequestMapping("/products")
   public String listProducts(Model model){

       model.addAttribute("products", productService.listAllProducts());

       return "products";
   }
}    

or

import org.springframework.web.bind.annotation.ResponseBody;

...

@Controller
public class ProductController {

   private ProductService productService;

   @Autowired
   public void setProductService(ProductService productService) {
       this.productService = productService;
   }

   @RequestMapping("/products")
   @ResponseBody
   public String listProducts(Model model){

       model.addAttribute("products", productService.listAllProducts());

       return "products";
   }
}    


**********EDIT**********

The @RestController or @ResponseBody only render string or JSON string.

For Template, do not need @RestController or @ResponseBody.

First, try:

application.properties

spring.thymeleaf.enabled=true
spring.thymeleaf.check-template-location=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.mode=HTML
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.suffix=.html

And put your templates file into resources/templates.

Second, adding a dependency to pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

And do not forget to reload all maven projects to download the new dependency.

Third, you should add <html lang="en" xmlns:th="http://www.thymeleaf.org"> to template file.

Forth, the template file name should be the same as the return clause in the controller. When you have return "products" in the controller, you should have the products.html template file in the templates folder.

Floorman answered 1/7, 2022 at 6:37 Comment(0)
H
1

Rename "product.ftl" to "products.ftl".

Harbinger answered 18/4, 2018 at 11:40 Comment(0)
C
1

In my case circular view path in spring boot 2 and jdk 11 was fixed by redirecting to index.html:

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            }
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("redirect:/index.html");
            }
        };
Camilla answered 6/4, 2021 at 15:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.