DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler - spring-boot

I am trying to design a rest api, and below is my controller code.
when i invoke http://localhost:8080/ the response is fine, but if i hit http://localhost:8080/api/ca it thorws javax.servlet.ServletException: No adapter for handler [...CaDetailController#48224381]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
#RestController("/api")
public class CaDetailController {
private static final Logger logger = LoggerFactory.getLogger(GetClassLoader.class.getClass());
#Autowired
CaService caService;
#RequestMapping(path = "/ca", method = RequestMethod.GET)
public #ResponseBody List<CaDetail> getCorporateActions() {
logger.info("CaDetailController.findAllCaDetails()");
return caService.findAllCaDetails();
}
#RequestMapping(path = "/ca/{caId}", method = RequestMethod.GET)
public #ResponseBody List<CaDetail> getCorporateActions(#PathParam("caId") long caId) {
logger.info("CaDetailController.getCorporateActions() : caId : " + caId);
return caService.findAllCaDetails();
}
}
Updated controller.
#RestController
#RequestMapping("/api/ca")
public class CaDetailController {
private static final Logger logger = LoggerFactory.getLogger(GetClassLoader.class.getClass());
#Autowired
CaService caService;
#GetMapping(path = "/")
public #ResponseBody List<CaDetail> getCorporateActions() {
logger.info("CaDetailController.findAllCaDetails()");
return caService.findAllCaDetails();
}
#GetMapping(path = "/{caId}")
public #ResponseBody List<CaDetail> getCorporateActions(#PathParam("caId") Long caId) {
logger.info("CaDetailController.getCorporateActions() : caId : " + caId);
return caService.findAllCaDetails();
}
}

For clarity, fix is:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/api/ca")
public class CaDetailController {
#GetMapping
public String healthcheck1() {
return "ok!";
}
#GetMapping(path = "health")
public String healthcheck2() {
return "ok again!";
}
}
You can call this endpoints using URL:
http://localhost:8080/api/ca and
http://localhost:8080/api/ca/health
(Assuming default Spring Boot Tomcat configuration).

Don't add ("/api") value to #RestController Annotation,
add it to #RequestMapping
#RestController
#RequestMapping("api/")
...

Try this
#RestController
#RequestMapping("/api")
public class CaDetailController {
instead of
#RestController("/api")
public class CaDetailController {

Related

how to split resource in spring boot

In Jersey we can do something like
#Path("/")
public class TopResource{
#GET
public Response getTop() { ... }
#Path("content")
public ContentResource getContentResource() {
return new ContentResource();
}
}
public class ContentResource {
#GET
public Response getContent() { ... }
}
so,
https://<host> will invoke getTop()
https://<host>/content will invoke getContent()
is there any equivalent in Spring?
I tried
#RestController
#RequestMapping("/")
public class TopResource{
#GetMapping()
public Response getTop() { ... }
#RequestMapping("content")
public ContentResource getContentResource() {
return new ContentResource();
}
}
#RestController
public class ContentResource {
#GetMapping()
public Response getContent() { ... }
}
only top resource works. content would return 404 Not Found.
Not sure how to do this in Spring Boot.
Tried replacing #RestController with #Resource and #Controller for content, but still got 404 Not Found.
There is no option to retun a whole class, please use the Annotation #RequestMapping on top of your content class to split them up.
#RestController
#RequestMapping("/")
public class TopResource{
#GetMapping()
public Response getTop() { ... }
}
#RestController
#RequestMapping("content")
public class ContentResource {
#GetMapping()
public Response getContent() { ... }
}

Servlet using Controller Annotation

Unable to go to Servlet from hello.jsp to MainController Class. This is a maven project.
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class MainController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String welcome() {
return "Hello";
}
#RequestMapping("displayname")
public String displayName(HttpServletRequest request) {
System.out.println("Working till here");
String firstName = request.getParameter("firstName");
request.setAttribute("firstName", firstName);
return "displayName";
}
}
#RequestMapping(value = "/displayname", method = RequestMethod.POST)
public String displayName(HttpServletRequest request) {
System.out.println("Working till here");
String firstName = request.getParameter("firstName");
request.setAttribute("firstName", firstName);
return "displayName";
}
You can change method parameter on requestmapping annotation. Also you can get body in displayName method and redirect it. I checked that method is empty when it is not defined. Maybe you can use #PostMapping annotation and other annotations like #GetMapping, #PostMapping etc...

Spring Boot - #RestController annotation gets picked up, but when replaced with #Controller annotation, it stops working

Here is a dummy project for the same :-
BlogApplication.java
#SpringBootApplication
#RestController
public class BlogApplication {
public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
}
#GetMapping("/hello")
public String hello(#RequestParam(value = "name", defaultValue = "World") String name) {
return String.format("Hello %s!", name);
}
}
HtmlController.java
#Controller //does not work
OR
#RestController //works
public class HtmlController {
#GetMapping("/getHtmlFile")
public String getHtmlFile() {
return "Bit Torrent Brief";
}
}
Why is it that #RestController is able to map getHtmlFile but #Controller returns 404 when /getHtmlFile is hit?
#RestController is the combination of #Controller and #ResponseBody.
when you use #Controller, you should write #ResponseBody before your method return type
#Controller
public class HtmlController {
#GetMapping("/getHtmlFile")
public #ResponseBody String getHtmlFile() {
return "Bit Torrent Brief";
}
}
This works.

Abstract class and url mapping

I have an abstract class
I try to have all generic method in this class.
I get issue about mapping.
public abstract class BaseControllerNew<T extends BaseEntity, R extends BaseDto, S extends BaseSearch> {
...
#GetMapping(value = "/{id}")
public R getById(#PathVariable("id") Integer id){
return baseServiceNew.getById(id);
}
#GetMapping(value = "/")
public Page<R> get(Pageable page){
return baseServiceNew.get(page);
}
....
}
#RequestMapping(value = "/rest/vehicules")
#RestController
public class VehiculesRestController extends BaseControllerNew<Vehicules, VehiculesDto, VehiculesSearch>{
private VehiculesServiceImpl vehiculesService;
#Autowired
public VehiculesRestController(final VehiculesServiceImpl vehiculesService) {
super(vehiculesService);
this.vehiculesService = vehiculesService;
}
I'm able to call
/rest/vehicules/1
but i get 404 for
/rest/vehicules
The problem is with your additional "/", this means your URL will be "/rest/vehicules/"
You only need #GetMapping
#GetMapping
public Page<R> get(Pageable page){
return baseServiceNew.get(page);
}

Creating controllers hierarchy with #RestController (spring boot application)

I want to create an hierarchy in my spring boot application controllers. Meaning: when requesting a path in one controller he will return the next controller.
It doesn't work...
In the example I created I expected to answer url:
/v1/notifications/test - should work
/v1 - shouldn't work
/v1/notifications - shouldn't work
/test - shouldn't work
etc...
This is what I did so far:
Controller root:
#RestController
#RequestMapping("/")
public class BaseController {
#Autowired
BaseControllerV1 baseControllerV1;
#RequestMapping(value = "/v1")
public BaseControllerV1 getBaseControllerV1(){
return baseControllerV1;
}
}
Controller child:
#RestController
public class BaseControllerV1 {
#Autowired
NotificationsControllerV1 notificationsControllerV1;
#RequestMapping(value = "/notifications")
public NotificationsControllerV1 getNotificationsControllerV1() {
return notificationsControllerV1;
}
}
Controller grandchild:
#RestController
public class NotificationsControllerV1 {
#RequestMapping(value = "/test",
method = RequestMethod.GET,
produces = "application/json")
public String getTest(){
return "{test: ok}";
}
}

Resources