Whats the use of mapping #requestMapping onto an entire class? - spring-mvc

This is an extremely basic question about spring MVC i have seen a few examples where the #RequestMapping sits above the class name of a Controller :
#RequestMapping
public class somethingController {
.
.
.
}
I understan the use of RequestMapping when it comes to methods but i haven't been able to understand the use of mapping it onto an entire class. What is it used for?
thanks in advance.

It allows mapping all the methods to a URL, or a URL prefix, or other restrictions. Further restrictions (like POST/GET, or URL suffix, etc.) can then be defined by a RequestMapping annotation on the methods. These method-level restrictions will either complement or override the restrictions placed on the type-level annotation.
The attributes that can be used at class or method or both levels, and how they behave, are specified in the javadoc.
For example:
#RequestMapping(value = "/foo", produces = "test/html")
public class SomeController {
#RequestMapping(method = RequestMethod.GET)
public String method1() {
...
}
#RequestMapping(method = RequestMethod.POST)
public String method1() {
...
}
}
In this example, both methods are mapped on /foo and produce HTML, but the first one is called when the HTTP method is GET, whereas the second one is called when the HTTP method is POST.

Related

How to validate url parameters bundle in parameter object in Spring's #RestController

I have a standard #RestController method. I introduced a parameter-object (MyMapQuery) in order to avoid large number of method arguments:
#RestController
public class MyController {
#RequestMapping(value = "/api/search")
#ResponseBody
public SearchResponse search(MyMapQuery query) {
[...]
}
MyMapQuery is a standard java bean with setters and getters, so when I pass multiple url parameters http://.../api/search?west=1&east=2&north=20&south=0, they are correctly filled in.
How do I implement required validation on some of the url parameters?
Spring automatically responds with 400(bad request), when parameters are mapped like below, but does no validation in case of MyMapQuery.
public SearchResponse search(#RequestParam BigDecimal east, #RequestParam BigDecimal west, ...) {
Just use
public SearchResponse search(#Valid MyMapQuery query) {
and add the necessary bean-validation annotations to the fields of MyMapQuery.

Create entities with custom mime type as addition to spring data rest controller

I have #Entity called Scenario. I have a #Repository for it and spring data rest which generates MVC controller for the CRUD operations. The path is /api/scenarios. Works.
I want to be able to POST to the /api/scenarios endpoint not only with the default JSON but also with multipart/form-data so I can create my Scenario from a file which the user uploads. I tried creating custom #Controller:
#RestController
public class ImportController {
#ResponseStatus(HttpStatus.CREATED)
#RequestMapping(value = "/api/scenarios", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Void> uploadScenario(#RequestPart(name = "scenario") MultipartFile scenarioFile) {
...
}
}
With this the upload for multipart/form-data works but I can no longer access the enpoint with GET. I'm getting Method not allowed. Like if my custom controller hides the one generated by spring data rest.
Is there a way how to add such custom POST on top of the existing controller so I can create my Scenarios with both JSON and application/form-data mime types?
You need to specify this custom controller as repository controller than Spring will add your custom methods to that generated controller.
Please note, you don't need to add api base path to your controller mapping. So, your mapping here is "/scenarios", not "/api/scenarios"
#RepositoryRestController
#RequestMapping("/scenarios")
public class ImportController {
#ResponseStatus(HttpStatus.CREATED)
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Void> uploadScenario(#RequestPart(name = "scenario") MultipartFile scenarioFile) {
...
}
}

Specifying #RequestHeader once for all controllers in Spring Boot app

I have a Spring Boot app with multiple controllers serving various REST methods. Each of the methods require that the same header parameter be defined. Is there a way to specify something like the following one time for all controller methods?
public ResponseEntity get(#RequestHeader(value="NAME", required = true) String name, ...) {
...
}
Thanks.
You can probably achieve this using #ModelAttribute, like this:
public class Something {
private name;
//...
}
#ModelAttribute("something")
public Something addSomething(#RequestHeader(value="NAME", required = true) String name) {
return new Something(name);
}
#RequestMapping("/something")
public ResponseEntity get(#ModelAttribute Something something) {
//...
}
You can implement the #ModelAttribute populating method in a single Controller or in a #ControllerAdvice class, in order to assist multiple controllers. See reference documentation.

New implementation/method of existing request mapping in controller

I am trying to look for a way to extend a controller such that I can use the existing request mapping but with a different implementation/method tied to it.
Say for example, below is a code snippet from AdminBasicEntityController in BLC where viewAddEntityForm method is tied to /add request mapping. Now I want to have my own logic of showing entityForm(Say Product entity) using /add request mapping. Is it possible?
#Controller("blAdminBasicEntityController")
#RequestMapping("/{sectionKey:.+}")
public class AdminBasicEntityController extends AdminAbstractController {
#RequestMapping(value = "", method = RequestMethod.GET)
public String viewEntityList(HttpServletRequest request, HttpServletResponse response, Model model,
#PathVariable Map<String, String> pathVars,
#RequestParam MultiValueMap<String, String> requestParams) throws Exception {
// default implementation
}
#RequestMapping(value = "/add", method = RequestMethod.GET)
public String viewAddEntityForm(HttpServletRequest request, HttpServletResponse response, Model model,
#PathVariable Map<String, String> pathVars,
#RequestParam(defaultValue = "") String entityType) throws Exception {
// default implementation
}
}
Also I found below mentioned information in the documentation of AdminBasicEntityController, so does it mean I can have controller for specific entity. If yes, how?
The default implementation of the {#link #BroadleafAdminAbstractEntityController}. This delegates every call to super and does not provide any custom-tailored functionality. It is
responsible for rendering the admin for every entity that is not
explicitly customized by its own controller
#RequestMapping("/{sectionKey:.+}") uses the generic path variable sectionKey, making the controller handle any requests that are not explicitly mapped. For example,
/product
/product/add
/category
/category/add
/store
/store/add
may all be hitting this controller if these URLs have not been explicitly mapped to their own controllers.
To handle a specific URL yourself, you could do:
#Controller
#RequestMapping("/product")
public class ProductAdminController {
#RequestMapping("/add")
public String viewAddEntityForm(...) { ... }
}
Now, the URL /product/add will be routed to this custom controller while all others will continue to get routed to the generic controller.

Difference Between Static or NoneStatic Methods in ASP.NET MVC

I need a method that return me some parameters in controllers this is implementation of it:
public List<Parameter> GetParameters(FormCollection collection) {
List<Parameter> parameters = new List<Parameter>();
List<string> parameterNames = new List<string>();
//Get Parameters Names and Values
return parameters;
}
I use this method in all of controllers, So I think about 3 option that I have to define it:
1-For any controller class define it in that controller like this:
public class ProductController : Controller {
public List<Parameter> GetParameters(FormCollection collection) {
//
}
}
2-Define it in static class as static method:
public static class GeneralMethods {
public static List<Parameter> GetParameters(FormCollection collection) {
//
}
}
3-Define it as a None Static :
public class GeneralMethods {
public List<Parameter> GetParameters(FormCollection collection) {
//
}
}
which one is better? which one have better performance? or any other option for define methods that used in many controllers?
what is your suggestion?
There will be no performance impact in any of the three. (Though last approach will create separate object each time,it will be gracefully handled by GC).
approach 1: NO, as a standard practice we should not duplicate the code.
approach 2: YES, if your method depends only on the input parameter.
approach 3: YES, if you need to set up some instance variable and your method depends on them.
suggested approach: (approach 1+ approach 3)
If this method is common to all of your controller (or most), declare a base controller with this method and inherit all other controller from it.
Static methods will not be a problem as any variable declared with in a method are with in scope of the method.

Resources