Jersey 2: What replaces FEATURE_FILTER_FORWARD_ON_404? - jersey

What is the Jersey 2 equivalent of ServletContainer.FEATURE_FILTER_FORWARD_ON_404 from Jersey 1?
ServletContainer.FEATURE_FILTER_FORWARD_ON_404 is defined as:
If true and a 404 response with no entity body is returned from either the runtime or the application then the runtime forwards the request to the next filter in the filter chain
Please explain why you are downvoting. I can't improve the question/answer if you don't provide an explanation of what is wrong.

The properties you should be using are ServletProperties.FILTER_FORWARD_ON_404 and ServletProperties.FILTER_STATIC_CONTENT_REGEX.
ServletProperties.FILTER_FORWARD_ON_404 is defined as:
If set to true and a 404 response with no entity body is returned from either the runtime or the application then the runtime forwards the request to the next filter in the filter chain.
ServletProperties.FILTER_STATIC_CONTENT_REGEX is defined as:
If set the regular expression is used to match an incoming servlet path URI to some web page content such as static resources or JSPs to be handled by the underlying servlet engine.

#gili is correct. For a complete running example of the jersey 2.x config check out my simple toy project on github:
https://github.com/depsypher/flapjack
Essentially you'll have to run the Jersey ServletContainer as a filter and provide the jersey.config.servlet.filter.forwardOn404 property as an init param.
Here's an example of the setup using Spring Boot; the web.xml equivalent should be pretty obvious:
FilterRegistrationBean filter = new FilterRegistrationBean(new ServletContainer());
filter.addInitParameter("jersey.config.servlet.filter.forwardOn404", "true");

Related

Spring MVC: log all requests, even the resource not founds

How can I log all requests in Spring MVC, even the resource not founds ones?
I guess interceptors can not log resource not found requests. What do you suggest?
Have you tried using implementation of javax.servlet.Filter?
Filter in contrary to Spring's interceptor is part of a Java's standard and is executed by the servlet container for each incoming HTTP request..
Spring MVC use exactly one servlet and that is DispatcherServlet which, as the name suggest, disptach received request to correct controller which process the request futher.
Spring even provide few concrete implementations of Filter that can log incoming request for you such as: CommonsRequestLoggingFilter or ServletContextRequestLoggingFilter.
You can choose one of the above implementations or implement Filter interface by yourself - whatever you decide, by using Filter you should be able to log every single request received by your servlet container.

Spring Boot + Jersey type filter - Bad request 400 for service Consumes MULTIPART_FORM_DATA

I'm using Spring boot v1.5.10 + Jersey v2.25.1, configured jersey as filter to access static folder files. I'm getting HTTP response 400 Bad Request for a service consuming MULTIPART_FORM_DATA.
Props to configure Jersey as filter.
spring.jersey.type=filter
If I remove above property i.e., using Jersey as Servlet, the service is working, but I'm not able to access static folder.
Here is the controller,
#POST
#Path("/save")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
public ResponseBean save(
#FormDataParam("fileToUpload") InputStream file,
#FormDataParam("fileToUpload") FormDataContentDisposition fileDisposition,
#FormDataParam("fromData") FormDataDto data) {
// stuff
}
EDIT:
GitHub link https://github.com/sundarabalajijk/boot-jersey
When you start the app, spring.jersey.type=filter
http://localhost:8080/ (works)
http://localhost:8080/hello.html (works)
http://localhost:8080/save (not working) - used postman.
When spring.jersey.type=servlet
http://localhost:8080/ (works)
http://localhost:8080/hello.html (not working)
http://localhost:8080/save (works)
After some research and finding related issues1, it seems that Spring's HiddenHttpMethodFilter reads the input stream, which leaves it empty for any other filters further down the filter chain. This is why we are getting a Bad Request in the Jersey filter; because the entity stream is empty. Here is the note from the Javadoc
NOTE: This filter needs to run after multipart processing in case of a multipart POST request, due to its inherent need for checking a POST body parameter.
So what we need to do is configure the Jersey filter to be called before this Spring filter2. Based on the Spring Boot docs, there is a property we can use to easily configure the order of this filter.
spring.jersey.filter.order
Doing a Github search in the Spring Boot repo for the HiddenHttpMethodFilter, we can see the subclass that is used OrderedHiddenHttpMethodFilter, where the order is set to -10000. So we want to set the order of our Jersey filter to less than that (higher precedence). So we can set the following value
spring.jersey.filter.order=-100000
If you test it now, it should now work.
One more thing we need to fix is the order of the Spring RequestContextFilter. This is originally configured to be ordered to be called right before the Jersey filter. When we set the order configuration above for the Jersey filter, the RequestContextFilter stays where it was originally at. So we need to change this. We can do this just by adding a bean to override the original one and set the order.
#Bean
public RequestContextFilter requestContextFilter() {
OrderedRequestContextFilter filter = new OrderedRequestContextFilter();
filter.setOrder(-100001);
return filter;
}
Now if we check the logs on startup, we should see the filer ordering we want.
Mapping filter: 'characterEncodingFilter' to: [/*]
Mapping filter: 'requestContextFilter' to: [/*]
Mapping filter: 'jerseyFilter' to urls: [/*]
Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
Mapping filter: 'httpPutFormContentFilter' to: [/*]
Aside
The reason you need to configure Jersey as a filter in your case is because of the static content. If you don't configure the root path for the Jersey app, then it defaults to /*, which will hog up all requests, included those to the static content. So Jersey will throw 404 errors when requests are made for the static content. We configure Jersey as a filter and tell it to forward request that it cannot find.
If we were to just configure the root path for Jersey, then we would not need to worry about this problem with the static content, and we would be able to just leave Jersey configured as a servlet by default.
To change the base path for the Jersey app, we can either add the #ApplicatuonPath annotation to our ResourceConfig or we can use the property spring.jersey.application-path
#Component
#ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {
...
}
or in your application.properties
spring.jersey.application-path=/api
See also
File upload along with other object in Jersey restful web service. This has some information on how you can accept JSON as a body part in the multipart request.
Footnotes
1. Some issues to look at [ 1, 2 ]
2. See Change order of RequestContextFilter in the filter chain
I guess the accepted answer is not up to date anymore. With Spring Boot 2 I did not have such problems. There was one issue though. I had a custom filter which was calling getParameterMap on the request object. Apparently getParameterMap implicitly reads the input stream of the request which then gets closed afterwards so that no other code can read the request body anymore.
Strangely with the setting spring.jersey.type=servlet I could get the request body even though getParameterMap was called beforehand, so I guess the implementation of ServletRequest is different depending on what you have configured for spring.jersey.type.

Spring StandardServletMultipartResolver

I was wondering where is located the code that automatically create a temporary file when you send a multipart request using StandardServletMultipartResolver?
Can i disable that behavior? I want to decide how its going to be stored and where. I don't want spring to do it for me.
I'm considering creating my own resolver but I cant find information on how to disable spring default behavior.
To quote from API docs StandardServletMultipartResolver does not support temporary file configuration on resolver level rather it is to be done on servlet registration level -
In order to use Servlet 3.0 based multipart parsing, you need to mark the affected servlet with a "multipart-config" section in web.xml, or with a MultipartConfigElement in programmatic servlet registration, or (in case of a custom servlet class) possibly with a MultipartConfig annotation on your servlet class.
Configuration settings such as maximum sizes or storage locations need to be applied at that servlet registration level; Servlet 3.0 does not allow for them to be set at the MultipartResolver level.
So either you can configure it on servlet or switch to CommonsMultipartResolver which has the support to set the temp directory out-of-the-box as it inherits it from CommonsFileUploadSupport.setUploadTempDir (see respective docs here and here)

Spring security - implement oauth with existing FilterChainProxy

we have existing web application built with Spring security 3.1 ,Wink(for rest)
we now need to add oauth2 (client_credentials flow) for several resources, i looked into many examples and all of them using the Http namespace configuration along with spring dispatcher servlet (which we didn't have till now)
problem is that http namespace is creating a springSecurityFilterChain which we already had in the application , so first thing i renamed the existing filter so the default could co-exist with the old one.
but this does not work, its either the existing chain working for requests or the new one.
i have tried the following already
1. disabled dispatcher servlet context by giving empty config location (in web.xml)
2. tried to have the oauth configuration in application-context.xml (right to the existing FilterChainProxy)
3. Allow the /oauth/token in existing chain by setting its filter to none (so the new can take over)
4. tried to declare the oauth filters in the existing chain but there was a problem with its not getting the right clientAuthentication
i really don't know what else to try - so the question is : is it possible to have both declared in the same webapp ? or is it possible to declare oauth2 configuration in the old fashion.
thanks
Shlomi
I managed to do that eventually, having the API (protected with oauth) completey separated url from the rest of the application.
so the Http namespace is creating the springSecurityFilterChain bean and the others just have different bean names. everyone is delegated through the DelegatingProxy in web.xml
i needed to puth the API URL prefix in other chains and allow all requests through , leaving the oauth security chanin to deal with security.
(i.e filter-chain pattern="/api/**" filters="none)
regarding the spring oauth2 bounded to spring MVC so tight i think is not a good implementation.
the mapping of the dispatcher servlet cannot be for /* but have to be something like /auth/*
so a special filter inherit from ClientCredentialsTokenEndpointFilter with special path like super("/auth/oauth/token") was needed.
it also cannot be /api/* since this is the real API URI mapped by our rest framework (wink RestServlet)
so we have something like this
http://server:port/context/auth/oauth/token
http://server:port/context/api/someresource (protected with oauth2)
http://server:port/context/rest/someresource (old rest for application)
Shlomi

Spring MVC 3.0 - restrict what gets routed through the dispatcher servlet

I want to use Spring MVC 3.0 to build interfaces for AJAX transactions. I want the results to be returned as JSON, but I don't necessarily want the web pages to be built with JSP. I only want requests to the controllers to be intercepted/routed through the DispatcherServlet and the rest of the project to continue to function like a regular Java webapp without Spring integration.
My thought was to define the servlet-mapping url pattern in web.xml as being something like "/controller/*", then have the class level #RequestMapping in my controller to be something like #RequestMapping("/controller/colors"), and finally at the method level, have #RequestMapping(value = "/controller/colors/{name}", method = RequestMethod.GET).
Only problem is, I'm not sure if I need to keep adding "/controller" in all of the RequestMappings and no matter what combo I try, I keep getting 404 requested resource not available errors.
The ultimate goal here is for me to be able to type in a web browser "http://localhost:8080/myproject/controller/colors/red" and get back the RGB value as a JSON string.
You are not correct about needing to add the entire path everywhere, the paths are cumulative-
If you have a servlet mapping of /controller/* for the Spring's DispatcherServlet, then any call to /controller/* will be handled now by the DispatcherServlet, you just have to take care of rest of the path info in your #RequestMapping, so your controller can be
#Controller
#RequestMapping("/colors")
public class MyController{
#RequestMapping("/{name}
public String myMappedMethod(#PathVariable("name") String name, ..){
}
}
So now, this method will be handled by the call to /controller/colors/blue etc.
I don't necessarily want the web pages to be built with JSP
Spring MVC offers many view template integration options, from passthrough to raw html to rich templating engines like Velocity and Freemarker. Perhaps one of those options will fit what you're looking for.

Resources