Configure Spring interceptor for controllers only - java

I'm trying to configure a Spring interceptor for controllers only in the following way. For the beginning I want to exclude all the requests starting with /swagger. I try to do it in the following way:
registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/swagger**");
However, interceptor gets fired. Where is a mistake?
Maybe, there is an alternative solution with #ControllerAdvice. But I need to get request headers, so I guess it doesn't fit my needs.
Thanks for any help!

Try to use "/swagger*/**" or "/swagger*" instead of "/swagger**"

I solved the problem in the following way:
#ControllerAdvice
public class SomeAdvice {
#ModelAttribute
public void token(HttpServletRequest request) {
// getting headers and setting the attribute in the request
request.setAttribute("theAttribute", new SomeObject());
}
}
And then I get the request attribute in a controller this way:
public void someMethod(#RequestAttribute("theAttribute") SomeObject someObject) {
// some logic goes here
}
P.S. And one more note. If you're using Swagger you'll get into the trouble as Swagger will consider this attribute as controller method parameter. To ignore it you can use the following snapshot of configuration:
.ignoredParameterTypes(SomeObject.class);

Related

No cache header in Spring Boot response from RestController

I have a typical controller which returns JSON and I need to return no-cache header as a part of a response. Please note at this moment I have no spring security on classpath, however if there is need to make it to work out-of-the-box then I'm fine with this.
Currently I have implemented this in the following manner:
public static <T> ResponseEntity<T> createResponseSpringWay(final T body) {
org.springframework.http.CacheControl cacheControl = org.springframework.http.CacheControl.noCache();
return ResponseEntity.ok().cacheControl(cacheControl).body(body);
}
Is there any spring boot property that can make it automatically for me? I want to get rid of ResponseEntity at all methods.
I've tried the following configuration, but I believe it only applies to static resources, so it doesn't work:
spring.resources.cache.cachecontrol.no-store=true
spring.resources.cache.cachecontrol.must-revalidate=true
spring.resources.cache.cachecontrol.no-cache=true

How to test only specific http request method available for controller method in Spring MVC?

I need to check if only specific http method is available for some url.
For example, if there is a controller like this
#Controller
public class FooController {
#RequestMapping(value = "bar", method = RequestMethod.GET)
public void bar() {/*do something*/};
...
}
For controller test I use junit(4.10), spring-test(3.2.10) and easymock(3.1).
If I write test like this
#Test
public void testBar() throws Exception {
mockMvc.perform(post("bar").session(session))
.andExpect(/*some application's default error response*/);
}
it will pass (although test calls post-method, not get-method).
So I'm looking for a proper way to make sure, that my rest resources are only avaiable by request methods specified in documentation. Two solutions came to my mind:
write tests with wrong request methods and somehow check resource is not available
add custom exception resolver to process org.springframework.web.HttpRequestMethodNotSupportedException: Request method '__' not supported and return same application default error response, but with https status 405 Method not allowed.
What would you suggest and how to check in controller test request method?
Thanks in advance.
You would need to check the status of all the request methods, you could do it using andExpect with status().isMethodNotAllowed() or status().isNotFound() depends on your needs:
Examples:
get: mockMvc.perform(get("bar").andExpect(status().isNotFound()) or mockMvc.perform(get("bar").andExpect(status().isMethodNotAllowed())
Do the same same for put, delete, ....

Path Priority in RequestMapping

I already opened an issue for that here. But also i want to ask it to stackoverflow people.
#Controller
#RequestMapping("/xxx")
public class MyController {
#RequestMapping("/**")
public ModelAndView getPage() {
//some code
}
#RequestMapping("/**/yyy/")
public ModelAndView getPageSecond() {
//some code
}
#RequestMapping("/**/yyy/{pathVariable}")
public ModelAndView getPageThird(#PathVariable("pathVariable") Integer num) {
//some code
}
}
Assume that we have a simple Controller like that, and I am sending these requests :
1) /xxx/aaa/bbb/yyy/ -->okay it will be mapped with getPageSecond method and will do his work.
2) /xxx/aaa/bbb/yyy/23 --> I think it must be mapped with getPageThird method, but it is strange that Spring is catching this request via getPage method.
I tried to dive into Spring codes to understand whats going on there, then i found AntPatternComparator. This comparator is giving result in order to bracket count, taking the lesser one for best match.
Why? Third one is more specific then others, is there something wrong ?
You could manually add your own version of RequestMappingHandlerMapping to your application context and set its patternMatcher property using setPathMatcher(PathMatcher pathMatcher) with your own implementation that will correct the issue you're having.

How to pre-process the request body in Spring before passing it to the a Controller?

I am implementing a RESTful service and I would like to validate the XML against an XSD in an interceptor before passing it on the a CastorUnmarshaller.
Though, in the WebRequestInterceptor I have to read the request body which can only be read once so the unmarshaller cannot read it. Is there a way of doing it?
I know that I can do both the validation and the unmarshalling manually in the Controller, but I would like to use the #RequestBody <DomainObject> way to unmarhall it.
Alternatively, as another solution, is there a way to tell the CastorUnmarshaller to validate it against the xsd?
Quite a long time passed, but someone else might benefit from this:
You can define an #Around aspect and intercept the incoming requests and their respective bodies as follows:
#Aspect
#Component
public class RequestResponseLoggingAdvice {
private static final Logger logger = LoggerFactory.getLogger(RequestResponseLoggingAdvice.class);
#Pointcut("within(#org.springframework.web.bind.annotation.RestController*)")
public void restcontroller() {}
#Pointcut("#annotation(org.springframework.web.bind.annotation.PostMapping)")
public void postmapping() {}
#Around("restcontroller() && postmapping() && args(.., #RequestBody body, request)")
public Object logPostMethods(ProceedingJoinPoint joinPoint, Object body, HttpServletRequest request) throws Throwable {
logger.debug(request.toString()); // You may log request parameters here.
logger.debug(body.toString()); // You may do some reflection here
Object result;
try {
result = joinPoint.proceed();
logger.debug(result.toString());
} catch(Throwable t) {}
}
}
Please note that your REST controller methods have to have suitable signatures for the above aspect can hook in. A sample one could be as follows:
#PostMapping
public SampleDTO saveSample(#RequestBody Sample sample, HttpServletRequest request) {
//.....
}
You can probably attach a #Before aspect (spring AOP). There you can get the same request body parameter as passed to the controller method.
Another option is to wrap the request into one that supports reading the body multiple times (by caching it the first time)
A filter can also be used to validate the XML passed.
org.springframework.oxm.castor.CastorMarshaller has a validating property to enable validation on in- and out-going documents.
But enabling it in Spring-MVC's default marshaller must be solved.

Spring MVC 3 controller request handler common

I have a controller that handles few requests that have to be checked for existence of the same cookie value. This means that in each request handler I have to perform the same check.
#Controller
public class MyController {
#RequestMapping("/Path")
public String Handler1(#CookieValue(required = false, value = "Cookie") String cookie) {
if (cookie != null) {
handleNoCookie();
}
handleRequest1();
}
#RequestMapping("/AnotherPath")
public String Handler2(#CookieValue(required = false, value = "Cookie") String cookie) {
if (cookie != null) {
handleNoCookie();
}
handleRequest2();
}
and so on...
}
Is there a way to extract the duplicated check this into some method that will do the check before the actual handler executes?
Thanks.
You could use an interceptor to ... "intercept" requests and process your logic if the cookie isn't there. You can make it fire before the controller is hit via the preHandle method.
API: HandlerInterceptor
If there are a large number of Handler methods, you could look into Spring's AOP to implement the cookie check advice for all the methods.
http://static.springsource.org/spring/docs/2.5.x/reference/aop.html
AOP interceptor suggested in other answers is an configurational overkill.
Similar functionality can be achieved using #ModelAttribute annotation. It is available since Spring 2.5. Methods annotated using #ModelAttribute must generate parameters for the view model. These methods are called before every method annotated using #RequestMapping.
It seems to be working if the annotated method returns nothing (void-method). In this case it works as some imaginary "BeforeEveryRequest" annotation. It looks like this:
#ModelAttribute
public void tagController(HttpServletRequest request) {
request.setAttribute(VERSION_PARAMETER, version());
}
UPDATE:
There is a small side effect. It adds a dummi value to the model. Key is a string "void" and the value is null.

Categories

Resources