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