Reputation: 2735
I am writing a Spring Boot application. I have written a simple controller that gets invoked whenever the endpoint is hit, but it still returns status 404 and not the specified return value.
HelloController
@Controller
public class MessageRequestController {
@RequestMapping(method = RequestMethod.GET, value = "/hello", produces = "application/json")
public String hello() {
System.out.println("Hit me!");
return "Hello, you!";
}
}
Now whenever I call localhost:8080/hello
, I see the console log "Hit me!"
, but "Hello, you!"
is never returned. Postman outputs:
{
"timestamp": 1516953147719,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/hello"
}
Application.java
@SpringBootApplication
@ComponentScan({"com.sergialmar.wschat"}) // this is the root package of everything
@EntityScan("com.sergialmar.wschat")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Upvotes: 38
Views: 28055
Reputation: 12817
Change your method return a ResponseEntity<T>
@RequestMapping(method = RequestMethod.GET, value = "/hello", produces = "application/json")
public ResponseEntity<String> hello() {
System.out.println("Hit me!");
return new ResponseEntity<String>("Hello, you!", HttpStatus.OK);
}
or change the controller to RestController
@RestController
public class MessageRequestController {...}
CURL
ubuntu:~$ curl -X GET localhost:8080/hello
Hello, you!
Upvotes: 51
Reputation: 1854
When everything seems ok but receive 404, check this answer:
As you know:
In the Spring MVC you can return view as a String
or ModelAndView
object.
IMPORTANT NOTE:
In both cases you have to pay attention to relative/absolute path:
/
in the beginning of the view name, you are using absolute path.@RequestMapping
and directly introduce itself as the final view name./
in the beginning of the view name, you are using relative path (relative to the class path) and therefore it appends to the class level @RequestMapping
to construct final view name.So, you have to consider the above notes when use the Spring MVC.
Example:
1. create two HTML file test1.html
and test2.html
in the static
folder of spring (boot) structure:
Please note that the class level @RequestMapping
behaves as a folder path in the case of relative path.
--- resources
--- static
--- classLevelPath //behaves as a folder when we use relative path scenario in view names
--- test2.html //this will be used for relative path [case (2)]
--- test1.html //this will be used for absolute path [case (1)]
String
and ModelAndView
in both relative and absolute path.
@Controller
@RequestMapping("/classLevelPath")
public class TestController {
//case(1)
@RequestMapping("/methodLevelAbsolutePath1")
public String absolutePath1(Model model){
//model.addAttribute();
//...
return "/test1.html";
}
//case(1)
@RequestMapping("/methodLevelAbsolutePath2")
public ModelAndView absolutePath2(Model model){
ModelAndView modelAndView = new ModelAndView("/test1.html");
//modelAndView.addObject()
//....
return modelAndView;
}
//case(2)
@RequestMapping("/methodLevelRelativePath1")
public String relativePath1(Model model){
//model.addAttribute();
//...
return "test2.html";
}
//case(2)
@RequestMapping("/methodLevelRelativePath2")
public ModelAndView relativePath2(Model model){
ModelAndView modelAndView = new ModelAndView("test2.html");
//modelAndView.addObject()
//....
return modelAndView;
}
}
Note:
You can specify the suffix of your view files by a ViewResolver
(for example InternalResourceViewResolver
or spring.mvc.view.suffix=.html
in the appliction.properties
file of Spring Boot and do not declare .html
suffix in the above code.
Best Regard
Upvotes: 0
Reputation: 3169
Short version:
Annotate your endpoint method with ResponseBody to bind the return value to the response body.
@Controller
public class MessageRequestController {
@RequestMapping(method = RequestMethod.GET, value = "/hello", produces = "application/json")
@ResponseBody
public String hello() {
System.out.println("Hit me!");
return "Hello, you!";
}
}
You can instead annotate your class with RestController instead of Controller
to apply ResponseBody
to each method of the class.
@RestController
public class MessageRequestController {
@RequestMapping(method = RequestMethod.GET, value = "/hello", produces = "application/json")
public String hello() {
System.out.println("Hit me!");
return "Hello, you!";
}
}
With @Controller, you use the default model-view from Spring Web MVC, and you're actually telling spring to render the view called Hello, you!.tml
from your resources directory (src/main/resources/templates
for a Spring Boot project, if I remember correctly).
You can read this article for more information about the Spring MVC REST Workflow.
Once you're more familiar with those concepts, you can even further customize your endpoint method using ResponseEntity.
Upvotes: 16
Reputation: 52
As you see the "hit me", there's no mapping issue, but in your @RequestMapping annotation you specifie a produce type to "application/json" and you return a simple poor String not formatted and without any header('Content-Type: application/json').
Add the header and format the outpout.
Upvotes: 2