spring boot mapping without slash - spring-boot

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")
...
.
.
.
}

Related

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.

Spring Boot MVC request mapping overrides static resources

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.

Can I specify that a controller level request mapping is not valid for a specific method into a Spring MVC controller class?

I am working on a Spring MVC application and I have the following problem into a controller class that is annotated with #RequestMapping("/profilo/") at class level.
So I have something like this:
#Controller
#RequestMapping("/profilo/")
public class ProfiloController extends BaseController {
..................................................................
..................................................................
SOME CONTROLLER METHOD THAT WORK CORRECTLY
..................................................................
..................................................................
#RequestMapping(value = "utenze/{username}/confermaEmail/{email:.+}", method = RequestMethod.GET)
public String confermaModificaEmail(#PathVariable String username, #PathVariable String email, Model model) {
logger.debug("INTO confermaModificaEmail(), indirizzo e-mail: " + email);
.......................................................................
.......................................................................
.......................................................................
}
}
So, as you can see in the previous code snippet, I have this ProfiloController class that is annotated with #RequestMapping("/profilo/") so it means that all the HTTP Request handled by the controller method of this class have to start with the /profilo/ in the URL.
It is true for all the method of this class except for the confermaModificaEmail() method that have to handle URL as:
http://localhost:8080/my-project/utenze/mario.rossi/confermaEmail/a.nobili#siatec.net
that don't tart with /profilo/.
So can I specify that for this specific method of the controller the #RequestMapping("/profilo/") controller level mapping is not valid and have to be not considered?
This is not possible.
Spring has maintained a proper #Controller structure which says for all endpoints related to ControllerName (i.e .Portfolio in your case) should be kept in this class.
Ideally, any other url not related to the functionality should be kept as part of a different Controller class.
If still you want to keep in same controller, try calling the endPoint url confermaModificaEmail() by redirecting the http call from "/portfolio/<"sample"> to the required url. But this is not recommended.

Spring MVC Url Pattern Issue

I have an existing application ..where we have some jsp..in view folder of the
application Context.Now we need to migrate one of the JSP's to a spring mvc controller..
I was doing a sample application and this is what i observed...
if I have the pattern in web-xml as / and annotate the controller as
RequestMapping(value="/view/Track.jsp")
This doesnt work..but If I modify it as /view and
update it as
RequestMapping(value="Track.jsp") then it works..
What is the reason for this..and what should be the approach for the migration.
Spring MVC concatenates the mapping from the controller and the method. With your second mapping it results in: /view/Track.jsp - this is OK. When the mapping on th controller is /view/Track.jsp you probably don't have mapping on the method, right? That way spring don't know which method of the controller to call even if you got only one...
If you want to use only the mapping on the controller you can place #RequestMapping(method = RequestMethod.GET) on the method.
#Controller
#RequestMapping("/view/Track.jsp")
public class UserController {
#RequestMapping(method = RequestMethod.GET)
public String track( MapModel model ) {...}
}
Good practice is to use the mapping on the controller to "modulaize" your mappings if you got more controllers. That way you will prevent collision on the method mappings between controllers.

Spring MVC : how to get the mapped URI within a method marked with #RequestMapping

I'm currently working on a Spring MVC application and as I mapped, within the web.xml file, all incoming URL to a single DispatcherServlet, I wanted to know whether it would be possible to retrieve the URI that has been effectively mapped. Here's an example to illustrate my concerns :
import static org.springframework.web.bind.annotation.RequestMethod.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HomeController {
#RequestMapping(method={GET})
public String processAllRequest(){
return "viewName";
}
}
Since I've defined the URL-MAPPING in the web.xml as being "/*", all incoming requests will end up in my controller class, show above. For instance, both the following requests will be processed by the processAllRequest() method from my controller.
myApplicationContext/home
myApplicationContext/logout
Is it possible, somehow, to retrieve the mapped URI? That is, once I'm inside the processAllRequest(), how could I know if it's been called for .../home or .../logout?
Is it possible to retrieve this kind of info by injecting an HttpServletRequest or another object as argument of the method?
Spring does inject HttpServletRequest if you put it in your handler arguments, so you can do that if you like.
But if you need to distinguish between different URLs, just place them in different handlers:
#Controller
public class HomeController {
#RequestMapping(value="/home", method={GET})
public String processHome(){
return "viewName";
}
#RequestMapping(value="/login", method={GET})
public String processLogin(){
return "viewName";
}
}
The mapping in web.xml forwards all requests to the spring servlet. You can still write as many #Controllers as you like, and play with class-level and method-level #RequestMapping to split the application into logical components.
I might have formulated my question in an ambiguous way but what I was looking for, was rather path variable. So my problem was solved this way :
#Controller
public class HomeController {
#RequestMapping(value="/{uri}", method={GET})
public String processMappedUri(#PathVariable uri){
return uri;
}
}
With this solution whenever I request the following requests, the uri argument from my processMappedUri() method will hold the variable value :
myApplicationContext/home --> uri = home
myApplicationContext/logout --> uri = logout

Resources