3

I built a crud application called Employer. Operations are working fine however when it comes to display them in html console shows error Not Found

: Resource not found
2019-07-29 05:04:25.834 DEBUG 18656 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 404 NOT_FOUND
2019-07-29 05:04:25.834 DEBUG 18656 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error", parameters={}
2019-07-29 05:04:25.834 DEBUG 18656 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2019-07-29 05:04:25.834 DEBUG 18656 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2019-07-29 05:04:25.834 DEBUG 18656 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [{timestamp=Mon Jul 29 05:04:25 PDT 2019, status=404, error=Not Found, message=No message available,  (truncated)...]
2019-07-29 05:04:25.835 DEBUG 18656 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 404
2019-07-29 05:04:37.741 DEBUG 18656 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : GET "/favicon.ico", parameters={}
2019-07-29 05:04:37.742 DEBUG 18656 --- [nio-8080-exec-3] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []]
2019-07-29 05:04:37.754 DEBUG 18656 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : Completed 200 OK

I tried to restart the app and change the name of Entity,but it didnt work.Below are what I tried

EmployerController.java

package io.javabrains;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.hibernate.mapping.Index;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import io.javabrains.Entity.Employer;

@Controller
public class EmployerController {


    @Autowired
    private EmployerService service;




    @RequestMapping("/")
    public String newForm() {
        return "form1";
    }






     public List<Employer>getAllEmployers()
     {


        return  service.getAllEmployers();



     }

        @RequestMapping(value="/tables",method=RequestMethod.GET)

    public String getAllEmployers(Model model)
    {
         List<Employer>employers = service.getAllEmployers(); 
        model.addAttribute("Employer",employers);
        return "tables";
    }





      @RequestMapping("/employer/{id}") 
      public Employer getEmployer(@PathVariable Integer id) { 
          return service.getEmployers(id);
      }



    @RequestMapping(method=RequestMethod.POST,value="/employer")
    public void addEmployer(@RequestBody Employer employer) {
        service.addEmployer(employer);

    }


    @RequestMapping(method=RequestMethod.PUT,value="/employer/{id}")
    public void updateEmployer(@RequestBody Employer employer,@PathVariable int id) {
        service.updateEmployer(id,employer);
    }




      @RequestMapping(method=RequestMethod.DELETE,value="/create/{id}") 
     public void deleteEmployer(@PathVariable int id)
     {
          service.deleteEmployer(id);
     }




}

EmployerService.java

package io.javabrains;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import io.javabrains.Entity.Employer;

@Service
public class EmployerService {
    @Autowired
    private Repository repository;

    public List<Employer>getAllEmployers(){
        List<Employer>employers = new ArrayList<>();
        repository.findAll()
        .forEach(employers::add);
        return employers;

    }

    public void addEmployer(Employer employer) {
        repository.save(employer);
    }


    public void updateEmployer(int id, Employer employer) {
        repository.save(employer);
    }


    public void deleteEmployer(int id) {
        repository.deleteById(id);
        ;
    }



      public Employer getEmployers(int id) 
      { 
          return repository.getOne(id);

      }





}

Employer.Java

package io.javabrains;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import io.javabrains.Entity.Employer;

@Service
public class EmployerService {
    @Autowired
    private Repository repository;

    public List<Employer>getAllEmployers(){
        List<Employer>employers = new ArrayList<>();
        repository.findAll()
        .forEach(employers::add);
        return employers;

    }

    public void addEmployer(Employer employer) {
        repository.save(employer);
    }


    public void updateEmployer(int id, Employer employer) {
        repository.save(employer);
    }


    public void deleteEmployer(int id) {
        repository.deleteById(id);
        ;
    }



      public Employer getEmployers(int id) 
      { 
          return repository.getOne(id);

      }





}

table.html

 <tbody>
                    <tr th:each="$(employers)">
                      <td th:text="${employers.name}"></td>
                      <td th:text="${employer.position}"></td>
                      <td th:text="${employer.office}"></td>
                      <td th:text="${employer.age}"></td>
                     <td th:text="${employer.salary}"></td>
                    </tr>

....

Sangam Belose
  • 4,262
  • 8
  • 26
  • 48
Alex
  • 77
  • 2
  • 4
  • 12
  • 1
    Would you try replacing `@Controller` by `@RestController`? – fiveelements Jul 29 '19 at 12:22
  • Yes I tried to replace restController to Controller because RestController restricts the access to template and always returns String – Alex Jul 29 '19 at 12:29
  • As I have mentioned in the answer, if you want to continue with `@Controller `add `@ResponseBody` annotation as well along with `@RequestMapping`. – fiveelements Jul 29 '19 at 12:32
  • if I add @ResponseBody along with RequestMapping, controllers keeps returning the String as always – Alex Jul 29 '19 at 12:44
  • can you also post your pom.xml (Maven) or build.gradle (Gradle) in the question? I would like to see dependencies injected. Which template engine you are using? – fiveelements Jul 29 '19 at 12:55
  • the return string should match with name of the file. e.g it should be tables.html – Sangam Belose Jul 29 '19 at 13:15
  • The error message that you see is because of there is no mapping for /error endpoint – Sangam Belose Jul 29 '19 at 13:16
  • add error.html in your src/main/resources/templates/ – Sangam Belose Jul 29 '19 at 13:18
  • fiveelements yes I will post here – Alex Jul 29 '19 at 13:25
  • nz.net.ultraq.thymeleaf thymeleaf-layout-dialect 2.0.5 org.thymeleaf thymeleaf 3.0.0.RELEASE org.thymeleaf thymeleaf-spring4 3.0.0.RELEASE – Alex Jul 29 '19 at 13:28
  • btw,the problem is not its getting an error, the problem is it can not find the resource which is coming from database? – Alex Jul 29 '19 at 13:29
  • @Alex see my updated answer. You may try all three options I have used in my controller: `public ModelAndView getHelloTemplate()`, `public String getHelloTemplate(Model model)`, `public String getHelloTemplate(ModelMap model)`. Add this dependency in pom.xml: `org.springframework.boot::spring-boot-starter-freemarker`. If this works then your issue is very specific to Thymeleaf like view resolver is not configured etc. – fiveelements Jul 29 '19 at 14:02

1 Answers1

2

If you use @Controller (org.springframework.stereotype.Controller) in your controller class you also have to add @ResponseBody for each @RequestMapping or at the class level.

Alternatively, Spring has introduced @RestController (org.springframework.stereotype.Controller.RestController) that includes both @Controller and @ResponseBody.

Also, in the API can you try the following, I have tested now and it works.

@RequestMapping(path="/template")
public ModelAndView getHelloTemplate(){
    ModelAndView model = new ModelAndView();
    model.setViewName("hello");
    model.addObject("message", "Hello World");
    return model;
}

I have used spring-boot-starter-freemarker template engine and the the html file is placed under `src/main/resources/templates/hello.ftl'.

Now, I have tested the same code with Thymeleaf and it works.

pom.xml:

<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-freemarker</artifactId>-->
<!--<version>2.1.2.RELEASE</version>-->
<!--</dependency>-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.1.2.RELEASE</version>
</dependency>

Controller:

@Controller(value = "tvGuideController")
public class TvGuideController {
    @RequestMapping(path="/template")
    public ModelAndView getHelloTemplate(){
        ModelAndView model = new ModelAndView();
        model.setViewName("hello");
        model.addObject("message", "Hello World");
        return model;
    }

    @RequestMapping(path="/template1")
    public String getHelloTemplate(Model model){
        model.addAttribute("message", "Hello World 1");
        return "hello";
    }

    @RequestMapping(path="/template2")
    public String getHelloTemplate(ModelMap model){
        model.addAttribute("message", "Hello World 2");
        return "hello2";
    }
}

The running application with both Thymeleaf and Freemarker template engines are available at github Clone the repository and run the application:

git clone https://github.com/fiveobjects/reference.git
cd java/springboot
mvn spring-boot:run

URLs (port may be different for you):

http://localhost:8080/template
http://localhost:8080/template1
http://localhost:8080/template2

If you want to run freemarker instead of thymeleaf in pom.xml comment out thymeleaf dependency and uncomment freemarker dependency.

If this works for you then, certainly your pom.xml dependencies, application.properties, main Application class and the Controller need to be checked.

fiveelements
  • 3,649
  • 1
  • 17
  • 16