Spring MVC 4 Java Config with Static HTML Views - java

I am trying to build a single page HTML/Angular app backed by Spring MVC 4 without .jsp files.
When the user arrives to the root URL (http://myapp.com/ for example), I want to send the single page HTML document (index.html).
However, I am new to Spring MVC's Java config and cannot work out the proper combination of ServletMapping, ViewResolver, and ResourceHandler.
I know that there may be some additional configuration for the "default" or "index" page, but I may be mistaken.
So how do I make a Java configured Spring MVC 4 application send an html file?
File structure
/src
'-/main
|-/web-inf
'-/webapp
|-index.html (want to send this)
'-/app
|-/partials
'-app.js
WebAppConfig.java
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/").addResourceLocations("/index.html");
}
IndexController.java
#RequestMapping("/")
public void index() {
System.out.println("pls"); // executes
// Have tried returning "index" and "index.html"
}
WebInitializer.java
#Override
protected String[] getServletMappings() {
// have tried with "/" as well
return new String[] { "/*" };
}

I think you should add this:
<mvc:view-controller path="/" view-name="index"/>
in your dispathcer-servlet file.

Here are a few working solutions either way - in case anyone needs one for their specific use case.
If you DO NOT want to invoke a controller method and just serve the file.
WebInitializer.java:
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
Web.xml
<web-app>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
WebConfig.java
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("index.html").addResourceLocations("/index.html ");
}
If you DO want to invoke a controller method on landing.
No welcome file list is required in the web.xml
WebInitializer.java:
#Override
protected String[] getServletMappings() {
return new String[] { "/*" };
}
WebConfig.java
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("index.html").addResourceLocations("/index.html ");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setSuffix(".html");
return viewResolver;
}
Controller.java
#RequestMapping("/")
public String index() {
return "index";
}
Hope that helps somebody.

Related

Spring Boot 2 Maven Directory View Resolver

I currently have a Spring Boot application that is using React JS for the front end. I'm running inside Visual Studio, and via webpack, I'm compiling resources and outputting them to a Maven target folder. You can see the structure of the directory with the Java classes sitting inside the 'classes' folder and the client application sitting now inside the webapp folder - notice the index.html.
As this is a single page application I only need this page to resolve. As such my controller is configured to return the index file.
#SpringBootApplication
public class AdminApplication
{
public static void main( String[] args )
{
SpringApplication.run( AdminApplication.class, args );
}
}
#Controller
public class DefaultController
{
#RequestMapping( "/**" )
public ModelAndView reactApp()
{
return new ModelAndView( "index" );
}
}
Now. My problem comes with telling my view resolver to talk to this directory.
As you can see from the commented code, I've tried only a couple of hundred options for trying to get it to resolve the view. I've got the full file path to my project directory available on the documentRoot so if necessary and thought potentially I would need that.
I've put a breakpoint in the controller and this definitely does get hit, it just returns a 404 when trying to find the relevant view each time. Any guidance on what my viewResolver might need to look like appreciated. I can see there's a couple of Classes that may or may not be correct:
e.g. SpringResourceTemplateResolver and ClassLoaderTemplateResolver - not sure on which of these is most relevant for my requirements
#EnableWebMvc
#Configuration
public class MvcConfig implements WebMvcConfigurer,ApplicationContextAware {
private ApplicationContext context;
#Value("${server.document-root:}")
private String documentRoot;
#Override
public void setApplicationContext( ApplicationContext applicationContext ) {
this.context = applicationContext;
}
// private ITemplateResolver htmlTemplateResolver() {
// SpringResourceTemplateResolver resolver = new
// SpringResourceTemplateResolver();
// resolver.setApplicationContext(applicationContext);
// resolver.setPrefix(documentRoot);
// resolver.setCacheable(false);
// resolver.setTemplateMode(TemplateMode.HTML);
// return resolver;
// }
// #Bean
// public SpringResourceTemplateResolver templateResolver() {
// SpringResourceTemplateResolver templateResolver = new
// SpringResourceTemplateResolver();
// templateResolver.setPrefix( "/webapp/" );
// templateResolver.setCacheable(false);
// templateResolver.setSuffix(".html");
// templateResolver.setTemplateMode("HTML");
// return templateResolver;
// }
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(context);
resolver.setPrefix("templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
// public ITemplateResolver templateResolver() {
// ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
// templateResolver.setPrefix("templates/");
// templateResolver.setCacheable(false);
// templateResolver.setSuffix(".html");
// templateResolver.setTemplateMode(TemplateMode.HTML);
// templateResolver.setCharacterEncoding("UTF-8");
// return templateResolver;
// }
}
you don't need MvcConfig
just set the static-locations property in src/main/resources/application.properties to spring.resources.static-locations=classpath:/webapp/
map all possible request to your index-page like:
#GetMapping({"/index","/","/home"})
public String reactApp()
{
return "/index.html";
}
optional you could redirect the requests to your index-page
#GetMapping({"/index","/","/home"})
public String reactApp()
{
return "redirect:/index.html";
}
You don't need the MvcConfig class, Spring boot auto-configure the view resolver. All you have to do is to put your templates to the src/main/resources/templates/ directory and make a simple controller mapping like this
#RequestMapping(value = "/")
public String index() {
return "index";
}
in your home controller.
You can also check out this React.js and Spring example
you will need to configure your resource handler, that way:
#Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("file:/path/to/dir/webapp/");
}
}
Notice, that in unix you will use file:/ and for windows
file:///C:/path/to/dir/webapp/
And then redirect the/ to index.html
#RequestMapping
#RestController
public class IndexEndpoint {
#GetMapping("/")
public String reactApp() {
return "/index.html";
}
}
I have tested it on a MacOS and it worked prefect.

HTTP Status 404 on jsp spring mvc

I'm trying to develop a spring MVC project which has a index.jsp file as it's view. I searched and found I should do this by the help of two below configuration classes:
public class MainInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
public static HashMap<String, String> response_code = new HashMap<String, String>();
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { MainConfiguration.class,
WebSocketConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
Security.addProvider(new BouncyCastleProvider());
servletContext.addListener(new MainContextListener());
}
}
and this is MainConfiguration class:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = "-----")
public class MainConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/Content/**")
.addResourceLocations("/Content/");
registry.addResourceHandler("/Scripts/**")
.addResourceLocations("/Scripts/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver
= new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
I've configured my project to run on tomcat web-server inside intellij. but when index.jsp is directly in path : webapp/index.jsp it will be opened in browser after running the program but when I move it to a subfolder it doesn't.
Shouldn't this part of code give the address to spring so it find the url and don't give a 404 error?
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
You need to annotate your MainConfiguration.java with #Configuration. Also, you require to register an instance of the DispatcherServlet in the servlet context. Actually, you can refer - spring mvc with jsp example for detailed configurations.

Spring-mvc 406 NOT Acceptable URl

I saw the relevant questions in stackoverflow but i didn't find a solution to my problem.
This is my Initializer Class:
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
public static HashMap<String, String> response_code = new HashMap<String, String>();
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { MainConfiguration.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
Security.addProvider(new BouncyCastleProvider());
servletContext.addListener(new MainContextListener());
}
}
This is the Controller:
#RestController
#Component
public class MainController {
#RequestMapping(value = "/getAll", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Int addNumber (
#RequestParam(value = "number", defaultValue = "0",
required = false) int number ) {
// code to set and return number
}
}
This is the Structure of webapp folder:
main/webapp/index.jsp
Css and Scripts folders are in webapp folder.
and I'm trying to run the project on intellij using tomcat web server.
the problem is when I run the project, index.jsp opens in a browser but it gives 406 not acceptable uri error on getAll.
You intercept all URLs (CSS as well)
protected String[] getServletMappings() {
return new String[] { "/" };
}
You need tyo exclude resources from the intercepting. See e.g. Spring 4.x Java code-based configuration: Static resource files and Dispatcher servlet
This should work
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
But make sure that you put the static contents under resources folder.
Please note that webapp is not a part of the Java web application folder structure and that's the reason why the code you put in your previous comment is not working
after trying lots of ways I discovered I had missed one dependency in my pom file, so response wasn't sent as json and 406 error occured, the missing dependency was jackson:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

Spring MVC redirecting unnecessary urls to particular url [duplicate]

As you know, in XML, the way to configure this is:
<error-page>
<error-code>404</error-code>
<location>/my-custom-page-not-found.html</location>
</error-page>
But I haven't found a way to do it in Java config. The first way I tried was:
#RequestMapping(value = "/**")
public String Error(){
return "error";
}
And it appeared to work, but it has conflicts retrieving the resources.
Is there a way to do it?
In Spring Framework, there are number of ways of handing exceptions (and particularly 404 error). Here is a documentation link.
First, you can still use error-page tag in web.xml, and customize error page. Here is an example.
Second, you can use one #ExceptionHandler for all controllers, like this:
#ControllerAdvice
public class ControllerAdvisor {
#ExceptionHandler(NoHandlerFoundException.class)
public String handle(Exception ex) {
return "404";//this is view name
}
}
For this to work, set throwExceptionIfNoHandlerFound property to true for DispatcherServlet in web.xml:
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
You can also pass some objects to error view, see javadoc for this.
The most clean solution since spring 4.2 RC3 is using the new createDispatcherServlet hook within the class extending AbstractDispatcherServletInitializer (or indirectly through extending AbstractAnnotationConfigDispatcherServletInitializer) like this:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
/* ... */
#Override
protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
final DispatcherServlet dispatcherServlet = super.createDispatcherServlet(servletAppContext);
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
return dispatcherServlet;
}
}
Then you can use a global #ControllerAdvice (a class that is annotated with #ControllerAdvice) as described in the reference docs. Within the advice you can handle the NoHandlerFoundException with an #ExceptionHandler as described here.
This could look something like this:
#ControllerAdvice
public class NoHandlerFoundControllerAdvice {
#ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<String> handleNoHandlerFoundException(NoHandlerFoundException ex) {
// prepare responseEntity
return responseEntity;
}
}
Simple answer for 100% free xml:
Set properties for DispatcherServlet
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {AppConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
boolean done = registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); // -> true
if(!done) throw new RuntimeException();
}
}
Create #ControllerAdvice:
#ControllerAdvice
public class AdviceController {
#ExceptionHandler(NoHandlerFoundException.class)
public String handle(Exception ex) {
return "redirect:/404";
}
#RequestMapping(value = {"/404"}, method = RequestMethod.GET)
public String NotFoudPage() {
return "404";
}
}
Use code-based Servlet container initialization as described in the doc and override registerDispatcherServlet method to set throwExceptionIfNoHandlerFound property to true:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected void registerDispatcherServlet(ServletContext servletContext) {
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() may not return empty or null");
WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext,
"createServletApplicationContext() did not return an application " +
"context for servlet [" + servletName + "]");
DispatcherServlet dispatcherServlet = new DispatcherServlet(servletAppContext);
// throw NoHandlerFoundException to Controller
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
Assert.notNull(registration,
"Failed to register servlet with name '" + servletName + "'." +
"Check if there is another servlet registered under the same name.");
registration.setLoadOnStartup(1);
registration.addMapping(getServletMappings());
registration.setAsyncSupported(isAsyncSupported());
Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter : filters) {
registerServletFilter(servletContext, filter);
}
}
customizeRegistration(registration);
}
}
Then create an exception handler:
#ControllerAdvice
public class ExceptionHandlerController {
#ExceptionHandler(Exception.class)
public String handleException(Exception e) {
return "404";// view name for 404 error
}
}
Don't forget about using #EnableWebMvc annotation on your Spring configuration file:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages= {"org.project.etc"})
public class WebConfig extends WebMvcConfigurerAdapter {
...
}
In your web configuration class,
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter
Declare a bean as follows,
#Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
#Override
public void customize(ConfigurableEmbeddedServletContainer container)
{
ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html");
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html");
container.addErrorPages(error401Page,error404Page,error500Page);
}
};
}
Add the mentioned html files(401.html .etc) to /src/main/resources/static/ folder.
Hope this helps
For Java config there is a method setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound) in DispatcherServlet. By settting it to true I guess you are doing same thing
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
then you can can this NoHandlerFoundException.class in controller advice as stated in above answer
it will be like something
public class WebXml implements WebApplicationInitializer{
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
DispatcherServlet dp = new DispatcherServlet(context);
dp.setThrowExceptionIfNoHandlerFound(true);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", dp);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping(MAPPING_URL);
}
}
The solution proposed in comments above really works:
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration)
{
registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
}
A solution for Spring 5 and Thymeleaf 3.
In MyWebInitializer, enable exception throwing with setThrowExceptionIfNoHandlerFound(). We need to do casting to DispatcherServlet.
#Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
...
#Override
protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
var dispatcher = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
dispatcher.setThrowExceptionIfNoHandlerFound(true);
return dispatcher;
}
}
Create a controller advice with #ControllerAdvice and add error message to the ModealAndView.
#ControllerAdvice
public class ControllerAdvisor {
#ExceptionHandler(NoHandlerFoundException.class)
public ModelAndView handle(Exception ex) {
var mv = new ModelAndView();
mv.addObject("message", ex.getMessage());
mv.setViewName("error/404");
return mv;
}
}
Create 404 error template, which displays the error message. Based on my configuration, the file is src/main/resources/templates/error/404.html.
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>Resource not found</title>
</head>
<body>
<h2>404 - resource not found</h2>
<p>
<span th:text="${message}" th:remove="tag"></span>
</p>
</body>
</html>
For completeness, I add the Thymeleaf resolver configuration. We configure the Thymeleaf templates to be in templates directory on the classpath.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
#Autowired
private ApplicationContext applicationContext;
...
#Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
...
}
In springboot it is even simplier. Because of Spring autoconfiguration stuff, spring creates a bean org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties. This class is annotated with #ConfigurationProperties(prefix = "spring.mvc") and therefore it will seek for properties with spring.mvc prefix.
Part from javadoc:
Annotation for externalized configuration. Add this to a class definition or a
* #Bean method in a #Configuration class if you want to bind and validate
* some external Properties (e.g. from a .properties file).
You just have to add to your i.e. application.properties file following properties:
spring.mvc.throwExceptionIfNoHandlerFound=true
spring.resources.add-mappings=false //this is for spring so it won't return default handler for resources that not exist
and add exception resolver as follows:
#ControllerAdvice
public class ExceptionResponseStatusHandler {
#ExceptionHandler(NoHandlerFoundException.class)
public ModelAndView handle404() {
var out = new ModelAndView();
out.setViewName("404");//you must have view named i.e. 404.html
return out;
}
}

Spring MVC link with .jsp/.jsp suffix returns 404

I have a simple page called headers.jsp in my Spring-MVC (4.1.5.RELEASE) web-app which i would like to call up from my index page like this:
<body>
<c:url value="/headers" var="headersUrl1"/>
<c:url value="/headers.jsp" var="headersUrl2"/>
<c:url value="/headers.jspx" var="headersUrl3"/>
<ul>
<li>Works!</li>
<li>Does not work!</li>
<li>Does not work!</li>
</ul>
The first url (to /headers) works fine but the other two (with suffix .jsp/jspx) do not; result is a 404. I have a need for the links to work (in real life they come from a legacy database which i have to use). I have spent quite some time googling but found no solution as yet.
The requests to links are handled by the following controller code:
#Controller
public class HeadersViewController {
#RequestMapping(value = {"/headers"}, method = RequestMethod.GET)
public String getHeadersPage() {
return "headers";
}
#RequestMapping(value = {"/headers**"}, method = RequestMethod.GET)
public String getHeaderPages() {
return "headers";
}
#RequestMapping(value = {"/headers.jspx"}, method = RequestMethod.GET)
public String getHeaderPageJspx() {
return "headers";
}
#RequestMapping("/{name}.jspx")
public String getPageByName(#PathVariable("name") String name) {
return name;
}
}
None of the controller methods get called when requesting /headers.jsp or /headers.jspx.
Strangely enough when using spring-test and mock-mvc they do get fired and tests to check the mentioned url`s passes.
Any help greatly appreciated! The rest of the config code is given below.
Dispatcherservlet init:
public class DispatcherServletInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { SecurityConfiguration.class, WebMvcConfiguration.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Filter[] getServletFilters() {
return new Filter[] { new HiddenHttpMethodFilter() };
}
}
MvcConfiguration:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"nl.demo.web.controller"})
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/login");
registry.addViewController("/logout");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
viewResolver.setOrder(0);
return viewResolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Security config:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/images/**", "/js/**", "/css/**", "/fonts/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/index")
.failureUrl("/login?error=1")
.permitAll()
.and()
.httpBasic()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=1")
.permitAll();
}
#Autowired
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
String user = "test";
String password = "blabla";
String[] roleList = "USER,SUPERVISOR".split(",");
auth.inMemoryAuthentication()
.withUser(user)
.password(password)
.roles(roleList);
}
}
The most likely cause of your issue is that the *.jsp and *.jspx extensions are normally handled by the container. If you for example checkout tomcat's conf/web.xml you'll notice a configuration
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
Similar goes for other containers. That is why your tests are working, yet your real app request fail.
Your best option would be to implement a Filter, that will be mapped to the same pattern, and that will redirect the headers.jsp and headers.jspx, to be handled by the controller, while leaving the other requests to be processed by the container as they would normally be, you have an example at this question
The problem is that your servlet is mapped to / and not to /*. / is a special mapping meaning that Spring MVC DispatcherServlet receives all requests that have not been managed by anything else.
As JSP and JSF are automatically registered servlets, the servlet container tries to pass the request to a JSP (resp. JSF) file and if it does not find it immediately sends a 404 and does not try to pass it to the DispatcherServlet.
You should map the dispatcher servlet to /*. But beware in that case, all URL will be given to the dispatcher servlet, and you will have to do a special treatment for serving static resources : you must add an override for addResourceHandlers to your Spring MVC configuration file (extract from Spring Framework Reference Manual - Serving of static resources) :
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/");
}

Categories

Resources