-1

I want to create a spring app that doesn't use any XMLs at all (no web.xml no context.xml or anything). So far it seems to work quite fine, except that my view resolver has some problems and I cannot figure it out on my own.

here's my WebApplicationInitializer

public class AppConfig implements WebApplicationInitializer {

    private AnnotationConfigWebApplicationContext getContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation("fi.cogniti.service.config");
        return context;
    }

    @Override
    public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
        WebApplicationContext context = getContext();
        servletContext.addListener(new ContextLoaderListener(context));
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(
            context));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/*");

        // Enabling spring security
        // servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
        // .addMappingForUrlPatterns(null, false, "/*");
    }
}

and my spring configuration

@Configuration
@EnableWebMvc
@ComponentScan("fi.cogniti.service")
public class SpringConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
    }

    @Bean
    public ViewResolver getViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/pages/");
        resolver.setSuffix(".jsp");

        return resolver;
    }
}

and finally my controller

@Controller
@RequestMapping("/")
public class HomeController {

    @RequestMapping
    public String entry() {
        return "index";
    }
}

index.jsp is located in src/main/webapp/pages/index.jsp.

So, if in my controller I use the annotation @ResponseBody, then the controller gives me the response "index", hence I know that my configuration works at least to some extent, however, if I remove the annotation in hopes that it would return the content of index.jsp, I only get a 404 error.

Any suggestions?

Michael
  • 3,308
  • 5
  • 24
  • 36
Kamil Janowski
  • 1,872
  • 2
  • 21
  • 43

3 Answers3

0

Change:

    dispatcher.addMapping("/*");

To something that doesn't match everything (you will get this error otherwise). For example:

dispatcher.addMapping("*.html");

In this way, http://localhost:8080/.html should show the jsp (change the @RequestMapping("/") in the controller to something more 'human')

You also should change this line including WEB-INF:

resolver.setPrefix("/WEB-INF/pages/");

I'm not sure if WebApplicationInitializer is getting executed (check this, where they are suggesting to use ServletContextInitializer but it's still creating issues).

If this is the case, you couldn't use the .addMapping("*.html"). If this is the case, you can add the following lines to SpringConfig in order to achieve the same result:

@Bean
public DispatcherServlet dispatcherServlet() {
    return new DispatcherServlet();
}

@Bean
public ServletRegistrationBean dispatcherServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(
        dispatcherServlet(), "*.html");

registration
        .setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);

    return registration;
}
Community
  • 1
  • 1
Michael
  • 3,308
  • 5
  • 24
  • 36
0

Currently all your jsp files are accessible by everyone, it is recommended to put them in WEB-INF instead at the top level.

Then modify your configuration for the view resolver to the following.

@Bean
public ViewResolver getViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/pages/");
    resolver.setSuffix(".jsp");
    return resolver;
}

You don't need to set the viewClass property as that is determined for you.

Next add the following to have the DispatcherServlet pass on requests that it cannot handle itself. This is needed due to the fact that you mapped the servlet to /.

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}

With these 2 changes you have secured your jsps from being accessible by everyone and made default resources being handled again.

I would strongly suggest using Spring Boot as that would really simplify your life.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
-1

In your controller the method should look like:

@RequestMapping(method = RequestMethod.GET)
public ModelAndView entry() {
    return new ModelAndView("index");
} 
george
  • 3,102
  • 5
  • 34
  • 51
  • doesn't help. also returning string as name is officially supported by string and request method is not really mandatory. If not specified, should apply too all methods – Kamil Janowski Mar 24 '15 at 09:22
  • You can return a string but not a page by specifying String entry so the ModelAndView return type is absolutely mandatory – george Mar 24 '15 at 09:33
  • resolver.setPrefix("/pages/"); resolver.setSuffix(".jsp"); these two lines specify where jsp files shouldl be searched for and that those actually are jsps. If you return string without saying @ResponseBody spring is supposed to figure out on its own that it's supposed to be a name of the page, go to directory /pages and add the ".jsp" suffix. I know it works, I did that many times before with xml configuration. You can find a similar solution here http://www.tutorialspoint.com/spring/spring_web_mvc_framework.htm Also,like I mentioned before,your solution still doesn't solve the problem – Kamil Janowski Mar 24 '15 at 10:18