Mapping request parameter names to fields in #ModelAttribute - java

I want to add validation on each #RequestParam in a controller method, like #NotNull for strings, #Min for integers. So I decided to have one model class with all request parameters. But now I want to map request parameters names to the fields in ModelAttribute. For instance, something like
class Model{
#Param("user-id") //is there any such way
#Min(1)
private Integer id;
}
I am not able to find any such functionality. Can someone help?

Related

How to set up Spring Form and Thymeleaf to not changing the fields of object added as model attribute if the form inputs not explicitly use it?

If I have the DTO object, added as attribute model in controller. It has two business fileds, say
public class Owner {
private Long id;
private String firstName;
private String secondName;
}
in some spring form I'd like to change the first name only still using the Owner as DTO, and this form doesn't have the second name input at all. And I also don't want to place the second name to the form as hidden input for privacy reasons, for example, so I have the only input dealing with the first name in the form? Is there a way to place the DTO to the model with both first and second name and in the #PostMapping controller method still getting both first and second name in the #ModelAttribute parameter object of the method? i'm getting the second name null in this case.
If the model was added to model attribute via addAttribute("owner", owner), #SessionAttribute("owner") annotation over the #Controller-marked class together with using #ModelAttribute("owner") ownet in the controller method parameter is the decision that helps. With #SessionAttribute the data is not cleared by the form with all fields put to null values.
Explicit naming of #ModelAttribute("named_via_here") being the same as #SessionAttribute("named_via_here") is required (it may work without it, but not guaranteed)

Spring MVC - private field on entity not populated from POST

I have a private field name on an Entity class: Product, which doesn't have a setName() method due to the business logic not allowing names to be changed.
I have an endpoint of the form:
#RequestMapping(value = "/endpoint", method = POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public Product saveProduct(
#Validated(FormSubmission.class) Product product,
Errors errors,
#RequestParam("sellerId") long sellerId) { ... }
I was under the impression that Spring was able to populate private fields as well when parsing request bodies but the name property stays null after a correctly formatted POST request unless I add a setName() method to Product.
Is the setter a requirement?
The private modifier specifies that the member can only be accessed in its own class.
and if you are outside, you can't read/write.

How to validate request parameters in Spring?

Here s my CODE to start with:
PersonController.java
#RequestMapping(value = "/person", method = RequestMethod.POST)
public ResponseEntity<?> addPerson(#Valid Person p, HttpServletResponse response) {
...
}
Person.java
public class Person {
#NotNull
String name;
#NotNull
int age;
String gender;
}
The requirement is: When a POST request is made to /person, I want an exception to be thrown if the user did not specify a key for the string Name in the BODY of the request. The annotation #NotNull does not do this.
Is there another annotation that I can use in Person.java to achieve this? If not, is there some validation I could do in the addPerson method to ensure that an exception is thrown if one of the mandatory parameters are not there?
Actually the #NotNull annotation does exactly what you want but unfortunately it can't do it on int type since it can't be null. In order for it to work you need to change the age to Integer and then after the spring does the binding of values if both parameters are passed and they have values the validation will pass. Otherwise if they are passed with empty value or not passed at all the value will be null and the validation will fail. Just make sure that you don't have some constructor for Person that initializes the attributes to some values.
If you don't want to change it and use an int you can add HttpServletRequest request to the method arguments and check if there is a parameter age present with:
request.getParameter('age');
If it is null then no parameter was passed at all.
Hint: It may be that you are missing some configuration and the annotation are not processed at all, something like <mvc:annotation-driven/> or #EnableWebMvc or maybe you are missing an actual validator implementation like Hibernate Validator. It is hard to tell without a sample of your configuration.
First, you need to encapsulate the fields in your domain-classes. The spring container will use these getters and setters to manipulate the object.
Then, you can add constraints to these getters and setters (Bean Validation). If you added them correctly, Spring will catch errors when using the #Valid annotation (which you did). These errors will be added to the BindingResult, and can be shown in a jsp by using the Spring form tags.
<form:errors path="field_that_was_manipulated_incorrectly" />

Restrict JSON attributes for #RequestBody

This may be a simple task, but I couldn't find a way to do it. Basically, I need to disallow some parameters at the time of using #RequestBody annotation in my controller.
Here is my model:
#Data
public class MyModel {
private int id;
private String name;
}
What I want to do is at the time of response, I want both of the properties to be serialized to JSON, but at the time of create or update, I prefer not to receive id as part of #RequestBody deserialization.
Right now, if I pass id in the JSON body, Spring initializes a MyModel object with its id set to the passed value.
Reason? The ID cannot be generated until the model is created, so the app shouldn't allow the ID to be set. On update, the ID needs to be passed in the URL itself e.g. (PUT /mymodels/43). This helps following the REST principles appropriately.
So, is there any way to achieve this functionality?
Update 1:
Right now, I am stuck with using a request wrapper. I created a new class MyModelRequestWrapper with only name as its property, and have used it with the #RequestBody annotation.
How you do this depends on what version of Jackson you are using. It's basically possible by a combination of the annotations #JsonIgnore and #JsonProperty on relevant fields/getters/setters.
Have a look at the answers here: Only using #JsonIgnore during serialization, but not deserialization

Spring-MVC: Need the most simple example of form-processing, binding, and validation

I have a form:
<form action="/processform">
<input name="firstname" value="john" />
<input name="lastname" value="doe" />
</form>
I have a Person object:
public class Person {
private String firstname;
private String lastname;
// ... getters & setters ...
}
I want to receive this data, perform validation on it, and post it to a datastore.
How do I write a controller to do this? I understand that I could pass the parameters in as request parameters, but I think the "proper" way to do this is somehow bind the data from the form to the Person object and then receive that Person object in the controller and call a Validate object that is configured to receive the Person object.
After much reading, this step has confounded me. Can someone show me what is needed to "bind" the data, "validate" (e.g. a validator), and "process" the data (e.g. the controller, and in particular what gets passed to it as parameters)?
Here was the answer I was looking for, I didn't understand that Spring, by default, will take all of the parameters from the form submission (such as "firstname" and "lastname") and can create the object for you by calling the setter methods of these parameters.
The controller:
#Controller
public class MyFormProcessor {
#RequestMapping("/formsubmit")
public String handleForm(#Valid Person person, BindingResult errors, Map<String,Object> model){
// ...handle form...
}
}
Spring is essentially doing the following magic before calling handleForm for this request (obviously in a more extendable way than I depict for this simple example):
Person person = new Person();
person.setFirstname( request.getParameter("firstname") );
person.setLastname( request.getParameter("lastname") );
handleForm(person, anErrorsObject, new Model());
For validation you can either create your own validator (which I won't mention anything about here), or if you include Hibernate Validator in the classpath, then you can annotate the Person class (example below) and when you add the #Valid annotation as I depicted in the example above the Hibernate validator will validate the class based on those annotations and post any errors to the error object (a BindingResult object is an extension of Springs' Errors, and for simple examples the Errors object is the interesting component).
JSR-303 validation annotated Person class (for use with the #Valid option):
public class Person {
#NotNull
#Size(min=3, max=20)
private String firstname;
#NotNull
#Size(min=3, max=20)
private String lastname;
// ... getters & setters ...
}
Spring has a complete tutorial showing every aspect that you need. It's called "Petclinic". You can check it out from:
git https://github.com/SpringSource/spring-petclinic

Categories