Spring Boot on WildFly (or Undertow): Servlet Filter's orders are reversed - spring-boot

I deployed my Spring Boot Web application on WildFly 8.1, but now I have some trouble.
When application was deployed, FilterRegistrationBeans register Servlet Filters. I know FilterRegistrationBeans are oredered by AnnotationAwareOrderComparator, and those filters are registerd by that order. But when I access my application, Undertow calls filters by reversed order.
For example, if Spring Boot register filters like that:
errorPageFilter
metricFilter (from Spring Boot actuator)
characterEncodingFilter
hiddenHttpMethodFilter
springSecurityFilterChain (from Spring Security)
Undertow call those filters like that:
springSecurityFilterChain
hiddenHttpMethodFilter
characterEncodingFilter
metricFilter
errorPageFilter
How can I specify those filters order correctly? Some filter's order (like org.springframework.boot.context.web.ErrorPageFilter) was hard-coded in source, I can't specify that.

This appears to be an Undertow bug that occurs when matchAfter is false in FilterRegistrationImpl#addMappingForUrlPatterns, instead of inserting the filter before all declared filters it inserts it before all filters.

Related

spring boot servlet context vs application context

I Come from years with Spring MVC, I'm trying to understand some key differences with Spring boot.
With Spring MVC I used to make a very clear distinction between application context and servlet context(s).
With Spring boot it looks like the servlet context has been pretty much deprecated and all the beans created by means of autoconfig mechanism live in the app context.
you can still create your servlet context of course, you have just to keep in mind the autoconfig is using application context.
so for example one implication of this is that #RestControllers and #Controllers live in the application context and the Spring Boot autoconfig servlet dispatchers will use any #RestController or #Controller annotated beans in the app context.
Can you help me confirm on this or make me understand what I'm missing here ?
In spring-springMVC system, there are two containers as your mentioned. For springboot-springMVC, debug in your controller and service with implementing ApplicationContextAware
they use the same global applicationContext
org.springframework.boot.web.servlet.contextAnnotationConfigServletWebServerApplicationContext

Is it possible to use DispatcherServlet as fallback when using Jersey starter in Spring Boot and embedded Tomcat?

Is it possible to have Jersey application on / but still allow DispatcherServlet to serve static content (eg from classpath:/whatever/path/here/) as a fallback?
I have tried to map DispatcherServlet to / and use JersetContainer (or something like that) to act as Filter instead of Servlet, however Jersey fallsback to default container servlet implementation which is DefaultServlet in my case.
So is it possible to have Jersey as a filter on the same mapping path with DispatcherServlet ??

Can I use Jersey as both servlet and filter in Spring Boot?

According to Spring documentation:
You can also use a Filter instead of a Servlet by setting spring.jersey.type=filter (in which case the #Bean to replace or override is jerseyFilterRegistration).
According to the answers to this question:
Use a Filter when you want to filter and/or modify requests based on specific conditions. Use a Servlet when you want to control, preprocess and/or postprocess requests.
So what if want to use Jersey with Spring Boot, to both serve json content and apply filters such as checking for authorisation and adding headers to all responses? The spring documentation reads like I have to choose either filter or servlet role for Jersey.
Can I do both with Jersey in a Spring Boot application and if so, how ?
So what if want to use Jersey with Spring Boot, to both serve json content and apply filters such as checking for authorisation and adding headers to all responses?
This question doesn't really make much sense.
Jersey itself is a processing engine. All it needs from the servlet container is the HttpServeltRequest and HttpServletResponse to start processing the request. These can be obtained both as a servlet Filter, or as a servlet HttpServlet. And if you look at the main Jersey servlet container component, ServletContainer, you will see that it both extends HttpServlet and implements Filter.
So being able to configure Jersey as a filter or as a servlet is not anything specific to Spring Boot; Jersey is designed this way. You could configure Jersey as a filter or servlet without Spring Boot.
As far as the filter system, Jersey has it's own filter system, independent of any servlet APIs. But if you want to use servlet filters, there's no reason you can't, whether or not you configure Jersey as a filter or as a servlet. If you understand the servlet filter chain, then you will know that filters get called one after the next, then the servlets are called. So if you want to add a filter and have it perform before the Jersey filter, you can do that. Or if Jersey is a servlet, your filter will be called before the Jersey servlet. Either way it is the same result. Jersey doesn't change any processing behavior just because it is a filter or if is a servlet.
The spring documentation reads like I have to choose either filter or servlet role for Jersey
Yes Servlet or Filter. Should be clear from what I mentioned above. You can have more than one servlet filter. Filters happen one after the other. You can add a filter that has nothing to do with Jersey. They all get passed the same ServletRequest and ServletResponse, so they all interacting with the same request and response. If you want to create a filter to add headers, then do it. It doesn't need to know anything about Jersey.
If you want to create Jersey specific filters (which is independent of any servlet filter mechanisms) for auth/headers and such, you can look at Filters and Interceptors (you can see an auth example in this great answer).
If you want to add servlet filters, then you can do so with FilterRegistrationBeans in Spring Boot.
#Bean
public FilterRegistrationBean anotherFilter() {
}

Servlet/Filters/Listeners in Spring Boot Application

I've added Servlet/Filters/Listeners in Spring Boot application using ServletRegistrationBean , FilterRegistrationBean etc.. for that we have to declare servlets, filters as spring bean ..which will get added in Spring Application Context..which is working absolutely fine
My Question is ..whenever i will call my application, will the request FIRST be handled by Dispatcher Servlet and then to Filter?
Before spring boot, we use to register it directly in web.xml and then i think Filters used to handler the request first, then dispatcher servlet and so on and so forth..
Has the flow changed in Spring Boot Application?

Spring 3.2 and #WebFilter annontation..is it supported?

I can't seem to find anything that talks about using the #WebFilter annotation, and having Spring 3.2 AbstractAnnotationConfigDispatcherServletInitializer correctly handle the params used.
Does Spring 3.2 support that annotation?
EDIT: based upon nicohlas answer
If I use the #WebFilter annontation, and set params inside of that...it looks like AbstractAnnotationConfigDispatcherServletInitializer registerServletFilter does not look at those annontations and setup things properly from those params: e.g url-mappings
Knowing that Spring 3.2 supports Servlet 3.0, shouldn't it support #WebFilter?
or am i missing the whole point of the WebFilter annontation?
EDIT 2:
When I deploy my war, and have #WebFilters defined inside that war, the container looks to "register" those...but, for some reason, even with the proper urlPatterns set, when the request comes into the DispatchServlet...it's like the filter doesn't get called.
#WebFilter is a JEE6 component, and is new to Servlet 3.0.
It is not something that Spring would support, but rather your application container (Tomcat, WebSphere, Glassfish, JBoss,...)
The idea here is to move configuration of your application container to Java, rather than utilizing the web.xml deployment descriptor.
EDIT:
It would seem to me that using the #WebFilter annotation would be for discovering Filter's via classpath scanning. The AbstractAnnotationConfigDispatcherServletInitializer#registerServletFilter method that you are asking about is taking in a Filter and does not look at the annotations on it.

Resources