How do I integrate Sitemesh 3 with Spring MVC 3? - spring-mvc

I am trying to use Sitemesh 3 to control the decoration of JSP output from a Spring MVC application.
When I hit the application it seems that Sitemesh is making a request to the Spring servlet to try and retreive its decorator file. This may, or may not be correct behaviour but it is causing me all many of headaches.
My understanding of Sitemesh 3 is that it does its work after Spring, ie on the Response object.
The error I'm getting in the browser is a 404 and in the logs (config/code follows):
INFO: Server startup in 1367 ms
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name
'springiness' processing GET request for [/clientmanager/]^M
DEBUG:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
Looking up handler method for path /^M
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
Returning handler method [public java.lang.String
uk.co.hermes.HomeController.home(java.util.Locale,org.springframework.ui.Model)]^M
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning
cached instance of singleton bean 'homeController'^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - Last-Modified value for
[/clientmanager/] is: -1^M
INFO : uk.co.hermes.HomeController - Welcome home! The client locale is en_GB.^M
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking
afterPropertiesSet() on bean with name 'home'^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - Rendering view
[org.springframework.web.servlet.view.JstlView: name 'home'; URL [/WEB-
INF/jsp/home.jsp]] in DispatcherServlet with name 'springiness'^M
DEBUG: org.springframework.web.servlet.view.JstlView - Added model object 'serverTime'
of type [java.lang.String] to request in view with name 'home'^M
DEBUG: org.springframework.web.servlet.view.JstlView - Forwarding to resource [/WEB-
INF/jsp/home.jsp] in InternalResourceView 'home'^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed
request^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name
'springiness' processing GET request for [/clientmanager/WEB-
INF/decorators/mainDecorator.html]^M
DEBUG:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
Looking up handler method for path /WEB-INF/decorators/mainDecorator.html^M
DEBUG:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
Did not find handler method for [/WEB-INF/decorators/mainDecorator.html]^M
WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request
with URI [/clientmanager/WEB-INF/decorators/mainDecorator.html] in DispatcherServlet
with name 'springiness'^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request^M
I suspect it's a problem in my web.xml and how I've defined the mappings(URLs):
<servlet>
<servlet-name>springiness</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springiness</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>sitemeshfilter</filter-name>
<filter-class>uk.co.hermes.filters.SitemeshFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemeshfilter</filter-name>
<!-- leaving SitemeshFilter class to decide which responses it should decorate -->
<url-pattern>/*</url-pattern>
</filter-mapping>
My custom filter:
public class SitemeshFilter extends ConfigurableSiteMeshFilter {
private Logger log = LoggerFactory.getLogger(SitemeshFilter.class);
/**
* See http://wiki.sitemesh.org/display/sitemesh3/Configuring+SiteMesh+3
*/
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
log.debug("** hit the sitemesh filter");
// apply this decorator (template) to the path defined...
builder.addDecoratorPath("/*", "/WEB-INF/decorators/mainDecorator.html");
// ... when the response type matches one of these
builder.setMimeTypes("text/html", "application/xhtml+xml", "application/vnd.wap.xhtml+xml");
}
}
WEB-INF/
|-jsp
|-home.jsp
|-decorators
|-mainDecorator.html
And my super simple Controller:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}

Since no one has posted actual content, here you go:
in pom.xml add:
<dependency>
<groupId>org.sitemesh</groupId>
<artifactId>sitemesh</artifactId>
<version>3.0.0</version>
</dependency>
in WEB-INF/web.xml † add:
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
in WEB-INF/sitemesh3.xml add:
<sitemesh>
<mapping path="/*" decorator="/WEB-INF/decorator1.jsp"/>
</sitemesh>
in WEB-INF/decorator1.jsp add:
<html>
<head>
...
</head>
<body>
<sitemesh:write property='body'/>
</body>
</html>
† put this below your Spring Security Filter Chain if using Spring Security.

Here is another blog that shows the integration between Sitemesh 3 and Spring MVC

In my case, I used this little tutorial to make it works.

Related

URL pattern servlet mapping

I created hello world example using Spring MVC, but there is one thing I didn't understand in servlet URL mapping, I did the following in web.xml:
<servlet>
<servlet-name>HelloWeb</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWeb</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
now if I want to call the following controller:
#Controller
#RequestMapping("/hello")
public class HelloWorld {
#RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model){
model.addAttribute("message","hello world");
return "index";
}
}
it will work using the following link:
http://localhost:8080/test/hello
but when I change the servlet url-pattern to "/*" and try:
http://localhost:8080/hello
it doesn't work, shouldn't it match my servlet ? as * matches everything
When you register a servlet with "/*" then it will override all the servlet mappings if there are any. Hence it should be avoided. This overrides default servlet mapping as well hence all default url handling also overridden and hence any specific url matching fails. In your case it is /hello.
With your case, initially you registered with /test/* this registered all your URL's with /test and hence they got identified.
It doesn't work for /* because, you have not registered/created a controller for that pattern.
It worked for http://localhost:8080/hello because, you have controller #RequestMapping("/hello")
Just change the RequestMapping to #RequestMapping("/") for url-pattern /*

Character-encoding Spring MVC

I am having trouble with Turkish characters...In my JSP pages, there is no problem... but, when an alert come from Java side, Turkish character(ŞşİığĞüÜç...) seems like that (ı,?,ü,ç,Å,...)
In JSP pages, I use this code and ı can solve Turkish character problem
<%# page contentType="text/html;charset=UTF-8" language="java"%>
in Spring MVC config, I tried a lot of way but I didn't succeed... For example In my mvc config class, I set my MessageSource like that;
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(0);
return messageSource;
}
In this program, I try to reset password and I typed unregister email address..Finally I am getting exception and this following is exception code blog.
#Autowired
private MessageSource messages;
...
#ExceptionHandler({ UserNotFoundException.class })
public ResponseEntity<Object> handleUserNotFound(final RuntimeException exception, final WebRequest request) {
logger.error("404 Status Code", exception);
final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.userNotFound", null, request.getLocale()), "UserNotFound");
return handleExceptionInternal(exception, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
In my messages_tr_TR.properties file,
...
message.userNotFound=Kullanıcı Bulunamadı
...
but In JSP pages this alert shows like that;
Kullanıcı Bulunamadı
How can I solve this problem..
Comment follow-up, you can set the encoding in your response header as well. An example if you're returning json would be
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "application/json; charset=utf-8");
return handleExceptionInternal(exception, responseHeaders, HttpStatus.NOT_FOUND, request);
In web.xml:
<jsp-config>
<!-- global JSP configuration -->
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Put the actual text in the handler method (temporarily). Does it now look right? Is your messages file correctly saved as UTF-8? Also, I can't tell if you're using JSON or not...

Spring-mvc servlet mapping, is it possible to have "/" for servlet 1 and "/server/" for servlet 2?

Currently I have the following web.xml config:
<servlet>
<servlet-name>Website</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Website</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Server</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Server</servlet-name>
<url-pattern>/server/</url-pattern>
</servlet-mapping>
As for two example controllers:
#Controller
public class ApiRequests {
protected final Logger logger = Logger.getLogger(ApiRequests.class);
#RequestMapping(value = "api.json", produces = {"application/json"}, method = RequestMethod.GET)
#ResponseBody
public String handleActionJson(final HttpServletRequest request){
return "{test: 'blaat'}";
}
}
And
#Controller
#RequestMapping("/")
public class IndexController {
#RequestMapping("*.html")
public void showIndex(){
}
}
Now my problem is that when I try to call the /server/api.json url, the server won't give the json response, instead it gives me the following error:
PageNotFound:1108 - No mapping found for HTTP request with URI [/WorldDefense/server/api.json] in DispatcherServlet with name 'Website'
Which basically means its trying to search for /server/api.json in the Website servlet instead of the Server serlvet, as for my question: would it be possible to get this setup to work? (So /server/ to map to the Server servlet and all the other url combinations to the Website servlet)
Edit 1
I updated the code to reflect the changes as suggested by Costi Ciudatu but it still doesn't work. I removed the #RequestMapping("/server") and now only have the #RequestMapping at the handleActionJson method. Both resulting in these errors:
10:57:26,046 WARN PageNotFound:1108 - No mapping found for HTTP request with URI [/WorldDefense/server/server/api.json] in DispatcherServlet with name 'Website'
10:57:40,509 WARN PageNotFound:1108 - No mapping found for HTTP request with URI [/WorldDefense/server/api.json] in DispatcherServlet with name 'Website'
Mappings according to the tomcat log:
Server-servlet
11:03:49,655 INFO RequestMappingHandlerMapping:178 - Mapped "{[/api.json],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}" onto public java.lang.String com.world2.worlddefense.server.controllers.ApiRequests.handleActionJson(javax.servlet.http.HttpServletRequest)
11:03:50,125 INFO RequestMappingHandlerMapping:178 - Mapped "{[/api.json],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}" onto public java.lang.String com.world2.worlddefense.server.controllers.ApiRequests.handleActionJson(javax.servlet.http.HttpServletRequest)
Website-servlet
11:03:50,380 INFO RequestMappingHandlerMapping:178 - Mapped "{[//*.html],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public void com.world2.worlddefense.website.controllers.IndexController.showIndex()
11:03:50,381 INFO RequestMappingHandlerMapping:178 - Mapped "{[/login],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.world2.worlddefense.website.controllers.TempTestController.showTest()
You can define multiple DispatcherServlets in the same web.xml and map them as you wish. However, the servlet mapping should not be reflected in the #RequestMapping of your controllers. Your controllers always map to paths relative to the servlet mapping; in your case, I think you could get that JSON response if you tried /WorldDefence/server/server/api.json...
If you want different controllers to be associated with the two dispatchers, you only need to make sure that the proper controllers are loaded in the corresponding application context: Website-servlet.xml and Server-servlet.xml in case you stick with this convention.
Long story short, your mapping for ApiRequests should be '/', not '/server' and that controller should only be included in the "Server" dispatcher context.
As a side note, since 3.2.x, the .json extension is handled by the ContentNegotiationManager, so your controller should return some domain object which will be transparently marshaled by the Spring HttpMessageConverter mechanism and will thus be able to produce media types other than JSON with no effort.

URL mapping problems using Spring MVC

I have a very basic setup which I am trying to get working.
web.xml
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/site/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
mvc-dispatcher-servlet.xml
<context:component-scan base-package="com.blabla.controller" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/pages/" p:suffix=".jsp"
p:viewClass="org.springframework.web.servlet.view.JstlView" />
In the controller
#Controller
#RequestMapping(value = "/site")
public class SearchController {
#RequestMapping(value = "welcome", method = RequestMethod.GET)
public String test() {
return "test";
}
This is the problem that I have:
I would like to write /site/* as url-pattern in my web.xml, but when I do that I get
WARNING: No mapping found for HTTP request with URI [/site/welcome] in DispatcherServlet with name 'mvc-dispatcher'
When I write /site/welcome in full, everything works, but I dont want this because I dont want to add every page manually to the web.xml
And when I write "/*" as url-pattern i get the error message:
WARNING: No mapping found for HTTP request with URI [/WEB-INF/pages/test.jsp] in DispatcherServlet with name 'mvc-dispatcher'
which I guess makes sense because the the location of the jsp is included in the pattern.
So how do you do it: how can you be sufficiently vague in your url pattern without the problems I just had?

How can I change the default handler order of automatically added spring mvc handler

While implementing my project, I found that <mvc:resources/> was not working after I set up the controller using #RequestMapping(value = "/**") and #RequestMapping(method=RequestMethod.GET).
It seems that the annotated controller get a higher priority than the SimpleURLHandler.
Is there anybody who can solve this problem? I need that controller and cannot remove it.
Thanks in advance!
Here is how I set up the project and the details about the problem:
Web.xml
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
webmvc-config.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- The controllers are autodetected POJOs labeled with the #Controller annotation. -->
<context:component-scan base-package="com.web.test" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
<!-- Turns on support for mapping requests to Spring MVC #Controller methods
Also registers default Formatters and Validators for use across all #Controllers -->
<mvc:annotation-driven conversion-service="applicationConversionService"/>
<bean class="com.web.test.web.ApplicationConversionServiceFactoryBean" id="applicationConversionService"/>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources -->
<mvc:resources location="classpath:/META-INF/web-resources/, /WEB-INF/views/" mapping="/resources/**" cache-period="0" order="0"/>
<!-- Allows for mapping the DispatcherServlet to "/" by forwarding static resource requests to the container's default Servlet -->
<mvc:default-servlet-handler/>
<!-- selects a static view for rendering without the need for an explicit controller -->
<mvc:view-controller path="/" view-name="index"/>
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver" id="resourceBundleViewResolver" p:basename="META-INF/view/wicket-views" p:order="1"/>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="tilesViewResolver">
<property name="order" value="2"/>
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/views/layouts/layouts.xml</value>
<value>classpath:/META-INF/view/tiles-views.xml</value>
</list>
</property>
</bean>
... ...
</beans>
ApplicationController.java
#Controller
#RequestMapping(method=RequestMethod.GET)
public class ApplicationController {
#RequestMapping(value = "/**")
public ModelAndView handleRequest(HttpServletRequest request){
ModelAndView mav = new ModelAndView("index");
return mav;
}
}
Running log. (As you can see here, the resource request is processed by annotated controller, not the ResourceHttpRequestHandler).
2011-11-15 17:21:09,821 [http-8080-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.tiles2.TilesView: name 'index'; URL [index]] in DispatcherServlet with name 'Test'
2011-11-15 17:21:09,821 [http-8080-2] DEBUG org.apache.tiles.impl.BasicTilesContainer - Render request recieved for definition 'index'
2011-11-15 17:21:09,821 [http-8080-4] DEBUG org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'Test' processing GET request for [/Test/resources/javascripts/jQuery/jquery-ui-1.8.16.custom.min.js]
2011-11-15 17:21:09,823 [http-8080-4] DEBUG org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Matching patterns for request [/resources/javascripts/jQuery/jquery-ui-1.8.16.custom.min.js] are [/**/, /**]
2011-11-15 17:21:09,823 [http-8080-4] DEBUG org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - URI Template variables for request [/resources/javascripts/jQuery/jquery-ui-1.8.16.custom.min.js] are {}
2011-11-15 17:21:09,823 [http-8080-4] DEBUG org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Mapping [/resources/javascripts/jQuery/jquery-ui-1.8.16.custom.min.js] to HandlerExecutionChain with handler [com.web.Test.web.ApplicationController#1a57c9e4] and 4 interceptors
2011-11-15 17:21:09,823 [http-8080-4] DEBUG org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/Test/resources/javascripts/jQuery/jquery-ui-1.8.16.custom.min.js] is: -1
2011-11-15 17:21:09,823 [http-8080-4] DEBUG org.springframework.web.bind.annotation.support.HandlerMethodInvoker - Invoking request handler method: public org.springframework.web.servlet.ModelAndView com.web.Test.web.ApplicationController.handleRequest(javax.servlet.http.HttpServletRequest)
And if I remove the ApplicationController, the static resources can be reached.
2011-11-15 17:48:16,784 [http-8080-2] DEBUG org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'Test' processing GET request for [/Test/resources/styles/application-common.css]
2011-11-15 17:48:16,784 [http-8080-2] DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Matching patterns for request [/resources/styles/application-common.css] are [/resources/**]
2011-11-15 17:48:16,785 [http-8080-2] DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - URI Template variables for request [/resources/styles/application-common.css] are {}
2011-11-15 17:48:16,785 [http-8080-2] DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapping [/resources/styles/application-common.css] to HandlerExecutionChain with handler [org.springframework.web.servlet.resource.ResourceHttpRequestHandler#6cc5cbab] and 4 interceptors
By using value = "/**" you're saying your ApplicationController will handle absolutely all requested URLs.
Just specify a more restrictive pattern that your static content won't match and it'll work like you want it to; examples:
value = "/dynamic/**"
value = "/**/*.html"
value = "/pages/**"
The choice is up to you but the "RESTful" style is very hot these days, so I'd follow that style guide.
I had the same requirement.
I'm bundling a React app inside my Spring Boot app, but I want all the static resource requests to take highest priority, then fall-back to annotated controllers.
This way all urls that aren't actually static files will resolve to the index/root page of my React app.
For example -
/admin/css/style.css should resolve to a static file.
But a React route should resolve the root index page/view.
/admin/sub/path should resolve to a view.
This works by mapping all the paths in my annotated controller -
#Controller
public class DefaultMvcController {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
#GetMapping({ "", "/"})
public String index() throws IOException {
return "index";
}
#RequestMapping(path = {"/admin", "/admin/**"}, method = RequestMethod.GET)
public String admin() throws IOException {
return "admin/index";
}
}
And changing the order of the static file handler mapping to 1 less than the priority of the annotated controller mapping
#Configuration
#ComponentScan(basePackages = "net.savantly.sprout.controllers")
#RequiredArgsConstructor
public class SproutWebMvcConfigurer extends WebMvcConfigurationSupport {
#Bean
#Override
public HandlerMapping resourceHandlerMapping(UrlPathHelper urlPathHelper, PathMatcher pathMatcher,
ContentNegotiationManager contentNegotiationManager, FormattingConversionService conversionService,
ResourceUrlProvider resourceUrlProvider) {
HandlerMapping mapping = super.resourceHandlerMapping(urlPathHelper, pathMatcher, contentNegotiationManager, conversionService,
resourceUrlProvider);
((AbstractHandlerMapping)mapping).setOrder(-1);
return mapping;
}
}
Full source code here - https://github.com/savantly-net/sprout-platform/tree/development/spring/sprout-spring-boot-starter

Resources