javax.servlet.ServletException: Could not resolve view with name '/index' in servlet with name 'dispatcherServlet' - spring-boot

How can I resolve this issue. I am trying to redirect URL by adding trailing slash at the end of each view in spring boot application.
#Configuration
#ComponentScan
#EnableWebMvc
public class WebAppConfig extends WebMvcConfigurerAdapter{
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/about", "/about/").setKeepQueryParams(false).setStatusCode(HttpStatus.PERMANENT_REDIRECT);
registry.addRedirectViewController("/index", "/index/").setKeepQueryParams(flase).setStatusCode(HttpStatus.PERMANENT_REDIRECT);
}
}
MyController.java:
#RequestMapping(value= {"/index", "/"},method= {RequestMethod.GET,RequestMethod.POST})
public ModelAndView index(HttpServletRequest request, HttpSession session) {
ModelAndView modelAndView = new ModelAndView("/index/");
return modelAndView;
}
#RequestMapping(value= {"/about"},method= {RequestMethod.GET,RequestMethod.POST})
public ModelAndView about(HttpServletRequest request, HttpSession session) {
ModelAndView modelAndView = new ModelAndView("/about/");
return modelAndView;
}
index.jsp is located on /webapp/views
What I to do Configure anymore?

Related

Is there a way, value defined in one main controller, can be accessed from all the other spring mvc controller?

Something like this:
#Controller
public class HomeController {
public String getCurrentUserDetails() {
String username = "testuser";
return username;
}
}
#Controller
public class DashboardController {
#RequestMapping("/admin/dashboard")
public ModelAndView showDashbard() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("username", GET username FROM HOME CONTROLLER [HomeController's getCurrentUserDetails]);
modelAndView.setViewName("/admin/dashboard");
return modelAndView;
}
}
#Controller
public class ProfileController {
#RequestMapping("/admin/profile")
public ModelAndView showProfile() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("username", GET username FROM HOME CONTROLLER [HomeController's getCurrentUserDetails]);
modelAndView.setViewName("/profile/dashboard");
return modelAndView;
}
}
Yes I know I can instantiate the HomeController and get the object. But making object in every controller is hectic.
I just want the value of one controller available in all other controllers.

Spring Boot - Database based request mapping

Using Spring Boot 2 I want to create a database based request mapping. I mean, instead of using hundreds of #RequestMapping annotations on the controllers I would like to store the mapping in a database table.
Each of the controllers implements an interface that has an execute method so I simply search for the relevant controller in the DB and call the execute method on it.
At the moment I have a CustomController with a #RequestMapping("*") and this controller finds the real controller and calls the execute method. It works but it is not a good solution. For example at interceptor level the handler object is the CustomController and not the real controller.
Probably I should use the SimpleUrlHandlerMapping like this:
#Bean
public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
Map<String, Object> urlMap = new HashMap<>();
urlMap.put("/dashboard", __???__);
simpleUrlHandlerMapping.setUrlMap(urlMap);
return simpleUrlHandlerMapping;
}
But in this case I don't know how to fill the bean value in the urlMap. For example in case of "/dashboard" how to put the DashboardController.execute().
Maybe any better solution?
UPDATE 1
I have created a SimpleUrlHandlerMapping like this:
#Configuration
public class SimpleUrlHandlerMappingConfig {
#Autowired
private ApplicationContext context;
#Bean
public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
Map<String, Object> urlMap = new HashMap<>();
String path = "/dashboard";
String controllerName = "dashboardController";
Object myController = context.getBean(controllerName);
urlMap.put(path, myController);
simpleUrlHandlerMapping.setUrlMap(urlMap);
return simpleUrlHandlerMapping;
}
}
And a CustomHandlerAdapter as:
#Configuration
public class CustomHandlerAdapter implements HandlerAdapter {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public boolean supports(Object handler) {
logger.debug("Test handler: " + handler);
if (handler instanceof PageController) {
return true;
}
return false;
}
#Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.debug("Custom handle");
ModelAndView mv = new ModelAndView();
String viewName = ((PageController)handler).execute2(request, response);
mv.setViewName(viewName);
return mv;
}
#Override
public long getLastModified(HttpServletRequest request, Object handler) {
return -1;
}
}
But according to logs it seems that SimpleUrlHandlerMapping doesn't work correctly:
- DispatcherServlet with name 'dispatcherServlet' processing GET request for [/dashboard]
- Looking up handler method for path /dashboard
- Did not find handler method for [/dashboard]
- Matching patterns for request [/dashboard] are [/**]
- URI Template variables for request [/dashboard] are {}
- Mapping [/dashboard] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#4bc6044e]]] and 1 interceptor
- Test handler: ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#4bc6044e]]
- Last-Modified value for [/dashboard] is: -1
UPDATE 2
Thanks to #M. Deinum I have updated my code and have a working solution.
Please note that #EnableWebMvc was introduced and that can cause other side effects later.
The SimpleUrlHandlerMappingConfig:
#Configuration()
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleUrlHandlerMappingConfig {
#Autowired
private ApplicationContext context;
#Bean
#Order(Ordered.HIGHEST_PRECEDENCE)
public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
Map<String, Object> urlMap = new HashMap<>();
String path = "/dashboard";
String controllerName = "dashboardController";
Object myController = context.getBean(controllerName);
urlMap.put(path, myController);
simpleUrlHandlerMapping.setUrlMap(urlMap);
return simpleUrlHandlerMapping;
}
}
The CustomHandlerAdapter:
#Component
public class CustomHandlerAdapter implements HandlerAdapter {
#Override
public boolean supports(Object handler) {
if (handler instanceof PageController) {
return true;
}
return false;
}
#Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
ModelAndView mv = new ModelAndView();
String viewName = ((PageController)handler).execute2(request, response);
mv.setViewName(viewName);
return mv;
}
#Override
public long getLastModified(HttpServletRequest request, Object handler) {
return -1;
}
}
And the WebConfig:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/style/**")
.addResourceLocations("classpath:" + "/static/style/");
registry.addResourceHandler("/js/**")
.addResourceLocations("classpath:" + "/static/js/");
}
}
If I understood correctly, you want to get rid of the simple actions (get/post/put/delete) -- and those only call the save/find/delete methods from the repository.
If that is the case I suggest using Spring Data REST
I post the final solution (thanks to M. Deinum) here maybe helping somebody else.
So I only created a HandlerMapping using the SimpleUrlHandlerMapping:
#Configuration()
public class SimpleUrlHandlerMappingConfig {
#Autowired
private ApplicationContext context;
#Bean
public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
Map<String, Object> urlMap = new HashMap<>();
String path = "/dashboard";
String controllerName = "dashboardController";
Object myController = context.getBean(controllerName);
urlMap.put(path, myController);
simpleUrlHandlerMapping.setUrlMap(urlMap);
simpleUrlHandlerMapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
return simpleUrlHandlerMapping;
}
}
And a custom HandlerAdapter:
#Component
public class CustomHandlerAdapter implements HandlerAdapter {
#Override
public boolean supports(Object handler) {
if (handler instanceof PageController) {
return true;
}
return false;
}
#Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
ModelAndView mv = new ModelAndView();
String viewName = ((PageController)handler).execute2(request, response);
mv.setViewName(viewName);
return mv;
}
#Override
public long getLastModified(HttpServletRequest request, Object handler) {
return -1;
}
}
Please note that this example demonstrates only the concept without proper error handling and real DB access.

Controller are not working in Spring

I unable to understand why my controller are not redirecting to my html. Anyone can help me please?
WebConfig.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.udemy.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix("");
return resolver;
}
}
HelloWorldController.java
#Controller
#RequestMapping("/example")
public class HelloWorldController {
public static final String EXAMPLE_VIEW = "example.html";
#GetMapping("/")
public String fileUploadForm(Model model) {
return "fileDownloadView";
}
#GetMapping("/helloworld")
public String helloWorld(){
return "helloworld";
}
// #RequestMapping(value="/exampleString", method=RequestMethod.GET)
#GetMapping("/exampleString")
public String exampleString(Model model){
model.addAttribute("name","John");
return EXAMPLE_VIEW;
}
// #RequestMapping(value="/exampleMAV", method=RequestMethod.GET)
#GetMapping("/exampleMAV")
public ModelAndView exampleMAV() {
ModelAndView mav= new ModelAndView(EXAMPLE_VIEW);
mav.addObject("name", "Mike");
return mav;
}
AppInitializer
public class MyWebAppInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
My project structure is well done. So my html and jsps, are inside of the root WEB-INF/views. Also, the anotation #ComponentScan, are detecting the controller. So, its not a problem of root. Anyone can tell me, why im am not redirecting to the .html , please..
Error says:
ADVERTENCIA: No mapping found for HTTP request with URI [/spring-mvc-download-example/WEB-INF/views/example.html] in DispatcherServlet with name 'dispatcher'
In your controller class, above the
#RequestMapping("/example")
Insert:
#Controller
Gonna be:
#Controller
#RequestMapping("/example")
you have to annotate class HelloWorldController with #Controller or #RestController, only then it will be picked by #Componentscan annotation.

processFormSubmission not being called

I am new to spring. I am creating a simple login page. But the processFormSubmission() is not being called. But the showForm() is working.
public class LoginController extends SimpleFormController
{
private LoginService loginService;
private String loginView;
public LoginService getLoginService() {
return loginService;
}
public void setLoginService(LoginService loginService) {
this.loginService = loginService;
}
public String getLoginView() {
return loginView;
}
public void setLoginView(String loginView) {
this.loginView = loginView;
}
public LoginController() {
setBindOnNewForm(true);
}
#Override
protected ModelAndView processFormSubmission(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception
{
TraceUser tr = (TraceUser) command;
System.out.println(tr);
//loginService.
return super.processFormSubmission(request, response, command, errors);
}
#Override
protected ModelAndView showForm(HttpServletRequest request,
HttpServletResponse response, BindException errors)
throws Exception {
ModelAndView mav = new ModelAndView();
mav.addObject("traceUser", new TraceUser());
mav.setViewName(getLoginView());
return mav;
}
}
And please help me out with how should the ModelAndView object should be processed further.
First of all, the use of the Controller API has been left aside in favor of the new annotation-based controllers (see the #RequestMapping annotation) and classes like SimpleFormController have been deprecated since quite a while now.
However, to answer your question, I assume your form does not declare method="post" and by default, the SFC will consider only POST requests as form submissions (see the isFormSubmission() method in AbstractFormController). Is this the case ?

Spring mvc url parameter

I cannot display may restaurant.
I.ve got my controller class:
#Controller
public class RestaurantController extends MultiActionController{
private RestaurantDAO restaurantDAO;
public void setRestaurantDAO(RestaurantDAO restaurantDAO) {
this.restaurantDAO = restaurantDAO;
}
#RequestMapping("/restaurant/{restaurantId}")
public ModelAndView restaurantid(#PathVariable("contactId") int id,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
Restaurant restaurant = restaurantDAO.findRestaurantById(id);
ModelMap modelMap = new ModelMap();
modelMap.addAttribute("restaurant", restaurant);
return new ModelAndView("restaurant", modelMap);
}
}
im my jsp just:
<c:out value="${restaurant.name }"
in my spring-servlet.xml:
<bean name="/restaurant/**" class="web.RestaurantController" >
<property name="restaurantDAO" ref="myRestaurantDAO"/>
</bean>
Because you mixed up restaurantId and contactId
#RequestMapping("/restaurant/{restaurantId}")
public ModelAndView restaurantid(#PathVariable("contactId") ...
I guess when you change #PathVariable("contactId") to #PathVariable("restaurantId") it will work.
And add #RequestMapping("/restaurant/**") to your controller:
#RequestMapping("/restaurant/**")
#Controller
public class RestaurantController extends MultiActionController{
BTW: What is a MultiActionController?

Resources