Spring Boot MVC request mapping overrides static resources - spring-boot

I want to have rest controller in Spring Boot to handle all requests like this: "/{arg}", EXCEPT "/sitemap.xml". How can I achieve that?

You could specify your request mapping on the controller level via regex and exclude some resources (e.g. 'excludeResourceA' and 'excludeResourceB') with:
#RestController
#RequestMapping(value = "/{arg:(?!sitemap.xml|excludeResourceA|excludeResourceB).*$}")
public class YourRestController {
// your implementation
}
Of course you can also specify the request mapping on the method level with the same regex relative to your controller path matching and you can pass the argument with #PathVariable("arg") String arg in your method signature to your method body if you need it.

Related

spring boot mapping without slash

I'm having a controller mapping as shown below
#RestController
#RequestMapping("/v1/connector")
public class Controller
and the API mapping as below
#GetMapping("2/auth")
when I hit the URL it's giving me the response as request URL not found.
Can anyone tell why I'm getting this?
#GetMapping is a composed annotation that acts as a shortcut for #RequestMapping(method = RequestMethod. GET).
#RequestMapping maps HTTP requests to handler methods of MVC and REST controllers.
When you use a base path on your controller class, all controllers in that class accept URL paths that start with your given base path. In your case:
#RestController
#RequestMapping("/v1/connector")
public class Controller {
...
}
This means all of the controllers inside this class have the base path of /v1/connector and this means is a constant part of your URL and cant be changed.
So when you declare a #GetMapping("2/auth"), Spring will automatically add a / at the beginning of your path if there was no /. And your path will be http://YOUR-HOST-NAME/v1/connector/2/auth instead of http://YOUR-HOST-NAME/v1/connector2/auth.
See here for more clarification.
So If your application has paths like /v1/connector1, /v1/connector2, /v1/connector3, etc. It means the connector{n} is not constant and you must declare it on each of your controllers' methods separately.
#RestController
#RequestMapping("/v1")
public class Controller {
#GetMapping("/connector2/auth")
...
#GetMapping("/connector3/auth")
...
.
.
.
}

How to capture a common request parameter for all requests in spring BOOT REST

In Jersey Rest API
if any common request parameters are there then we can capture that value at RootResource level using the below code.
#QueryParam("q")
private String qQueryParams
Is there any similar approach in Spring Rest API.
In other words, all my endpoint URL will contain the query parameter "q". How to capture this data at class level instead of every request.
Thanks, Vijay
you can use #RequestMapping({q}/test) above controller and pass #PathVariable String q as method argument.
#Controller
#RequestMapping(value = "{q}/test")
class TestController {
#RequestMapping(value="/abc")
public ModelAndView doSomething(#PathVariable String q) {
// do something with q...
}
}

how to Enforce request header on all spring web RestController equests

Is there an option to specify a request header once in spring web RestController instead of doing it on every request?
e.q.
#RestController("workflowController")
public class MyClass{
public Value list(#RequestHeader(USER_ID_HEADER_PARAM) String user) {
...some code
}
public Workflow create(#RequestBody Workflow workflow, #RequestHeader(USER_ID_HEADER_PARAM) String user) {
... some code
}
}
the #RequestHeader(USER_ID_HEADER_PARAM) will be repeated in every request.
is there a way to specity it in the #RestCotroller level or the class level?
Thanks
Use some kind of filter class that can be configured to wrap around your requests in your servlets based on the URL path.
Here is info about the generic Servlet API filter API:
https://www.oracle.com/technetwork/java/filters-137243.html
If you're using Spring, there's another way to do it:
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#filters
https://www.baeldung.com/intercepting-filter-pattern-in-java

Automatically document #PathVariable annotated parameters within #ModelAttribute annotated methods

In our REST-API we need to be multi-tenant capable. For achiving this all rest controllers subclass a common REST controller which defines a request mapping prefix and exposes a model attribute as follows
#RequestMapping(path = "/{tenantKey}/api")
public class ApiController {
#ModelAttribute
public Tenant getTenant(#PathVariable("tenantKey") String tenantKey) {
return repository.findByTenantKey(tenantKey);
}
}
Derived controllers make use of the model attributes in their request mapping methods:
#RestController
public class FooController extends ApiController {
#RequestMapping(value = "/foo", method = GET)
public List<Foo> getFoo(#ApiIgnore #ModelAttribute Tenant tenant) {
return service.getFoos(tenant);
}
}
This endpoint gets well documented in the swagger-ui. I get an endpoint documented with a GET mapping for path /{tenantKey}/api/foo.
My issue is, that the {tenantKey} path variable is not documented in swagger-ui as parameter. The parameters section in swagger is not rendered at all. If I add a String parameter to controller method, annotating it with #PathVariable("tenantKey) everything is fine, but I don't want a tenantKey parameter in my controller method, since the resolved tenant is already available as model attribute.
So my question is: Is there a way do get the #PathVariable from the #ModelAttriute annotated method in ApiController documented within swagger-ui in this setup?
Project-Setup is
Spring-Boot (1.4.2)
springfox-swagger2 (2.6.1)
springfox-swagger-ui (2.6.1)
This is certainly possible. Model attributes on methods are not supported currently. Instead, you could take the following approach.
Mark the getTenant method with an #ApiIgnore (not sure if it gets treated as a request mapping.)
In your docket you can add tenantKey global path variable (to all end points). Since this is a multi-tenant app it's assuming this applies to all endpoints.

Mapping same URL to different controllers in spring based on query parameter

I'm using spring annotation based controller. I want my URL /user/messages to map to some controller a if query parameter tag is present otherwise to some different controller b. This is required because when parameter tag is present then some more parameters can be present along with that which i want to handle in different controller to keep the implementation clean.Is there any way to do this in spring. Also is there any other elegant solution to this problem ?
You can use the params attribute of the #RequestMapping annotation to select an controller method depending on Http parameters.
See this example:
#RequestMapping(params = "form", method = RequestMethod.GET)
public ModelAndView createForm() {
...
}
#RequestMapping(method = RequestMethod.GET)
public ModelAndView list() {
...
}
It is a REST style like Spring ROO uses: if the request contains the parameter forms then the createForm handler is used, if not the list method is used.
If you want to go the Spring route, you can checkout the HandlerInterceptor mentioned here. The Interceptor can take a look at your query param and redirect the link to something else that can be caught by another SimpleUrlMapper.
The other way is to send it to a single controller and let the controller forward to another action if the query parameter is "b".

Resources