I have asked a similar question before: this one
Now I have a similar but different issue.
My Spring MVC controller model is a JSON payload with a defined set of attributes that, unfortunately, are not part of a class in my project.
E.g.
{
"userId" : "john",
"role" : "admin"
}
I need to treat userId and role as separate Strings.
I currently have two ways to declare the controller method
public ResponseObject mvc(#RequestBody MyCustomDTO dto){
String userId = dto.getUserId();
String role = dto.getRole();
}
public ResponseObject mvc(#RequestBody ModelMap map){
String userId = (String)map.get("userId");
String role = (String)map.get("role");
}
I have been asked to find a different implementation because 1) requires to create a custom DTO class for each combination of parameters (most cases need 1 named parameter, e.g. delete(productId)) and 2) involves an entity that is not strictly defined. Especially when dealing with lists, it can contain arbitrary values that need to be checked at runtime.
Spring MVC, as I have found, does not support resolving #ModelAttribute from a JSON request body. Am I doing something wrong or is it just Spring not doing it? Can I grab a specific property, be it a plain primitive or an entire POJO, from the Request Body into a method argument?
In the second case it would be better to request a useful feature to Spring developers.
Spring version is 4.2.x.
This question is related with the previously linked but differs in the fact that now I will be encapsulating the single property into a Javascript object, so the object that Jackson needs to deserialize won't be a primitive but a POJO.
You won't be able to get individual members as easily, simply because Spring MVC doesn't have any builtin tools to do that. One option is to write your own annotation that describes a parameter at the root of an excepted JSON object body. Then write and register a new HandlerMethodArgumentResolver implementation which processes that annotation on a handler method parameter.
This is not a simple task. Since you can't consume the request content multiple times, you have to save it somehow, in a Filter, for example. For now, let's ignore this restriction and assume we only wanted one parameter. You'd define an annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
#interface JsonObjectProperty {
String name();
}
And the HandlerMethodArgumentResolver
class JsonObjectPropertyResolver implements HandlerMethodArgumentResolver {
/**
* Configured as appropriate for the JSON you expect.
*/
private final ObjectMapper objectMapper = new ObjectMapper();
#Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(JsonObjectProperty.class);
}
#Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
Class<?> parameterType = parameter.getParameterType();
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
MediaType contentType = inputMessage.getHeaders().getContentType();
if (!contentType.equals(MediaType.APPLICATION_JSON_UTF8)) {
throw new HttpMessageNotReadableException(
"Could not read document. Expected Content-Type " + MediaType.APPLICATION_JSON_UTF8 + ", was " + contentType + ".");
}
// handle potential exceptions from this as well
ObjectNode rootObject = objectMapper.readValue(inputMessage.getBody(), ObjectNode.class);
if (parameterType == String.class) {
JsonObjectProperty annotation = parameter.getParameterAnnotation(JsonObjectProperty.class);
return rootObject.get(annotation.name()).asText();
}
// handle more
throw new HttpMessageNotReadableException("Could not read document. Parameter type " + parameterType + " not parseable.");
}
}
and finally the handler method
#RequestMapping(value = "/json-new", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String handleJsonProperty(#JsonObjectProperty(name = "userId") String userId) {
String result = userId;
System.out.println(result);
return result;
}
You'll have to register the JsonObjectPropertyResolver appropriately. Once you do, it will be able to extract that JSON property directly into the parameter.
You can use some JSON inline parsers (similar to XML Xpath) where you can provide your JSON string and ask your parser to retrieve some subdocument as String, List or Map. One of the examples is OGNL. It's quite powerful tool, although it is not the only one and not the most performance efficient, but still mature and stable Apache product. So, in your case you would be able feed your JSON string to OGNL and tell it to retrieve properties "userId" and "role" as separate strings. See the OGNL documentation at Apache OGNL page
Related
Is there a way to custom validate 2 of request parameters coming into endpoint in Spring? I would like to be able to validate them with my custom function. Something like add annotation to the request params or on the function where these params are and force these params to be validated by another custom written function.
I need to take both params at the same time, because the validation output of one is dependent on the value of the other one.
I have searched and found some solutions with custom constraint annotations but from what I've read it doesn't seem to solve my problem.
As rightly mentioned, using valiktor is the best option. I have used it in our product as well and it works like a charm.
Below is a snippet example as how you are use it to compare two properties of the same class.
fun isValid(myObj: Myobj): Boolean {
validate(myObj) {
validate(MyObj::prop1).isGreaterThanOrEqualTo(myobj.prop2)
}
Valiktor throws exception with proper message if the validation fails. It also enables you to create custom exception messages if you want to.
Now all you need to do is, create a class for your requestBody and check your conditions with isValid() method explicitly or move it into init block and do it implicitly.
Valiktor has a large number of validations as compared to JSR380, where creating custom validation is a little messy as compared to Valiktor.
If you're going to use the request params to create a POJO, then you can simply use the Javax Validation API.
public class User {
private static final long serialVersionUID = 1167460040423268808L;
#NotBlank(message = "ID cannot be to empty/null")
private int id;
#NotBlank(message = "Group ID cannot be to empty/null")
private String role;
#NotBlank(message = "Email cannot be to empty/null")
private String email;
#NotNull(message = "Password cannot be to null")
private String password;
}
To validate -
#PostMapping("/new")
public String save(#ModelAttribute #Validated User user, BindingResult bindingResult, ModelMap modelMap) throws UnknownHostException {
if (!bindingResult.hasErrors()) {
// Proceed with business logic
} else {
Set<ConstraintViolation<User>> violations = validator.validate(user);
List<String> messages = new ArrayList<>();
if (!violations.isEmpty()) {
violations.stream().forEach(staffConstraintViolation -> messages.add(staffConstraintViolation.getMessageTemplate()));
modelMap.addAttribute("errors", messages);
Collections.sort(messages);
}
return "new~user";
}
}
You can write custom validator by using Validator
Check :: https://docs.spring.io/spring-framework/docs/3.0.0.RC3/reference/html/ch05s02.html
Example :: https://www.baeldung.com/spring-data-rest-validators
valiktor is really good library to validate.
You can do somenthing like:
data class ValidatorClass(val field1: Int, val field2: Int) {
init {
validate(this) {
validate(ValidatorClass::field1).isPositive()
validate(ValidatorClass::field2).isGreaterThan(field1)
}
}
}
make request parameter not required:
#RequestMapping(path = ["/path"])
fun fooEndPoint(#RequestParam("field1", required = false) field1: Int,
#RequestParam("field2", required = false) field2: Int) {
ValidatorClass(field1, field2) //it will throw an exception if validation fail
}
You can handle exception using try-catch or using and ExceptionHandler defined by valiktor.
Using valiktor you can validate fields depending on other fields. You can create one kotlin file where you write all classes that you use to validate fields from requests and in the same way you can use valiktor in you #RequestBody models to validate it.
I have the following controller. I am using Spring to create Restful APIs.
#RestController
public class UserController extends RestControlValidator {
#RequestMapping(value = "/user/", method = RequestMethod.POST, headers = "Accept=application/json", consumes = "application/json", produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody List newUser(#RequestBody #Valid UserInput input,BindingResult result)
{Some code}
}
The UserInput class looks like this:
public class UserInput{
#NotEmpty
private String emailId;
#NotEmpty
private String fName;
private String lName;
private int sex;
//getters and setters
Now when I try and access /user/ with data {"sex":"Male"}, I get the following response:
I want the response in case of such a request to be:
{"errors":{"sex":"The value must be an integer"}}
Is there any way of customising BAD REQUEST responses in Spring?
Considering the current scenario the most ideal solution would be to alter the behavior of HandlerMethodArgumentResolve as the json to pojo constructed by #RequestBody fails because we dont get a chance to check the wrong data and this check can very well be done in the custom message converter
A. first we would need to create LanguageMessageConverter as follows
public class LanguageMessageConverter extends
AbstractHttpMessageConverter<Language> {
private Gson gson = new Gson();
public LanguageMessageConverter() {
super(new MediaType("application", "json", Charset.forName("UTF-8")));
}
#Override
protected boolean supports(Class<?> clazz) {
return Language.class.equals(clazz);
}
Map<String, String> mp = new HashMap<>();
#Override
protected Language readInternal(Class<? extends Language> clazz,
HttpInputMessage httpInputMessage) throws IOException,
HttpMessageNotReadableException {
Map langmp = gson.fromJson(
convertStreamToString(httpInputMessage.getBody()), Map.class);
for (Field field : clazz.getDeclaredFields()) {
if (!langmp.get(field.getName()).getClass().getCanonicalName().equals(field.getType().getCanonicalName())) {
if (field.getType().getCanonicalName().equals("java.lang.Integer")||field.getType().getCanonicalName().toString().equals("int")) {
langmp.put(field.getName(), "0");
} else if (field.getType().equals("java.lang.String")) {
//TODO COde needs to be improved here because this check is not efficient
langmp.put(field.getName(), "wrong");
}
}
}
Language lang = gson.fromJson(gson.toJson(langmp), clazz);
return lang;
}
we need to set the media type new MediaType("application", "json", Charset.forName("UTF-8")) which will make sure this class intervenes the mentioned MIME type
Considering we need to manipulate the result I found it best to convert it to map langmp (There are better JSON Parsers which can be used)
Since we need to to understand the existing type I used reflection api to get the fields via getDeclaredFields()
Using the above made the logical check using the datatype to understand if the type is incorrect for eg if the field datatype is int and if it is found as String then corresponding map value will be substituted
once that is done the map will hold the updated values where in if the data was wrong a default value would be set eg if the int var is set to 0 since the originating json had a String in it.
Once that is done the updated map is converted to the concerned class.
B. Secondly we need to register the custom MessageConverter in the dispatcher xml i.e. LanguageMessageConverter
<mvc:annotation-driven >
<mvc:message-converters register-defaults="true">
<bean class="com.comp.org.controller.LanguageMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
register-defaults="true" is very important since we are adding Custom MessageConverter but we also need the other existing converters working along with the one we have added
LanguageMessageConverter needs to be registered here.
C. Considering the concerned pojo is populated with the necessary details it would reach our controller post processing in the custom converter now we would add the manual validation eg. if the int variable has 0 the necessary error json should be returned
As per your request even if the json consists of the wrong data the custom message converter should process it and accordingly in the controller we can validate the condition mentioned.
The code definitely can be improved further. Kindly let me know if this solution fulfilled your requirement or any part of the code requires further elaboration and hopefully addressed your concern.
I had the same issue, than I solved that way:
Create an Object called Error, like that (don't forget to implement Serializable...):
private String fieldName;
private String errorCode;
private String defaultMessage;
public Error() {
}
public Error(String fieldName, String errorCode, String defaultMessage) {
this.fieldName = fieldName;
this.errorCode = errorCode;
this.defaultMessage = defaultMessage;
}
/* getters, setters */
Inside the #RestController method you ave to call inputValidator.validate() method (if you didn't create an Object Validator for your UserInput then we're really don't speaking the same language...)
// validating the userInput
userInputValidator.validate(userInput, bindingResult);
if (bindingResult.hasErrors()) {
List<Error> errors = new ArrayList<>(bindingResult.getErrorCount());
for (FieldError fieldWithError : bindingResult.getFieldErrors()) {
errors.add(new Error(fieldWithError.getField(), fieldWithError.getCode(), fieldWithError.getDefaultMessage()));
}
return errors;
}
// in case of success:
return null;
Finally you'll have to translate the JSON object to your client side. You'll have two kind of objects:
3.1. null (undefined depending on the language you're using)
3.2. A JSON object like that:
[
{
"fieldName": "name",
"errorCode": "user.input.name.in.blank",
"defaultMessage": "Insert a valid name!"
},
{
"fieldName": "firstPhone",
"errorCode": "user.input.first.phone.blank",
"defaultMessage": "Insert a valid first phone!"
}
]
My question is essentially a follow-up to this question.
#RestController
public class TestController
{
#RequestMapping("/getString")
public String getString()
{
return "Hello World";
}
}
In the above, Spring would add "Hello World" into the response body. How can I return a String as a JSON response? I understand that I could add quotes, but that feels more like a hack.
Please provide any examples to help explain this concept.
Note: I don't want this written straight to the HTTP Response body, I want to return the String in JSON format (I'm using my Controller
with RestyGWT which requires the response to be in valid JSON
format).
Either return text/plain (as in Return only string message from Spring MVC 3 Controller) OR wrap your String is some object
public class StringResponse {
private String response;
public StringResponse(String s) {
this.response = s;
}
// get/set omitted...
}
Set your response type to MediaType.APPLICATION_JSON_VALUE (= "application/json")
#RequestMapping(value = "/getString", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
and you'll have a JSON that looks like
{ "response" : "your string value" }
JSON is essentially a String in PHP or JAVA context. That means string which is valid JSON can be returned in response. Following should work.
#RequestMapping(value="/user/addUser", method=RequestMethod.POST)
#ResponseBody
public String addUser(#ModelAttribute("user") User user) {
if (user != null) {
logger.info("Inside addIssuer, adding: " + user.toString());
} else {
logger.info("Inside addIssuer...");
}
users.put(user.getUsername(), user);
return "{\"success\":1}";
}
This is okay for simple string response. But for complex JSON response you should use wrapper class as described by Shaun.
In one project we addressed this using JSONObject (maven dependency info). We chose this because we preferred returning a simple String rather than a wrapper object. An internal helper class could easily be used instead if you don't want to add a new dependency.
Example Usage:
#RestController
public class TestController
{
#RequestMapping("/getString")
public String getString()
{
return JSONObject.quote("Hello World");
}
}
You can easily return JSON with String in property response as following
#RestController
public class TestController {
#RequestMapping(value = "/getString", produces = MediaType.APPLICATION_JSON_VALUE)
public Map getString() {
return Collections.singletonMap("response", "Hello World");
}
}
Simply unregister the default StringHttpMessageConverter instance:
#Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
/**
* Unregister the default {#link StringHttpMessageConverter} as we want Strings
* to be handled by the JSON converter.
*
* #param converters List of already configured converters
* #see WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)
*/
#Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.removeIf(c -> c instanceof StringHttpMessageConverter);
}
}
Tested with both controller action handler methods and controller exception handlers:
#RequestMapping("/foo")
public String produceFoo() {
return "foo";
}
#ExceptionHandler(FooApiException.class)
public String fooException(HttpServletRequest request, Throwable e) {
return e.getMessage();
}
Final notes:
extendMessageConverters is available since Spring 4.1.3, if are running on a previous version you can implement the same technique using configureMessageConverters, it just takes a little bit more work.
This was one approach of many other possible approaches, if your application only ever returns JSON and no other content types, you are better off skipping the default converters and adding a single jackson converter. Another approach is to add the default converters but in different order so that the jackson converter is prior to the string one. This should allow controller action methods to dictate how they want String to be converted depending on the media type of the response.
I know that this question is old but i would like to contribute too:
The main difference between others responses is the hashmap return.
#GetMapping("...")
#ResponseBody
public Map<String, Object> endPointExample(...) {
Map<String, Object> rtn = new LinkedHashMap<>();
rtn.put("pic", image);
rtn.put("potato", "King Potato");
return rtn;
}
This will return:
{"pic":"a17fefab83517fb...beb8ac5a2ae8f0449","potato":"King Potato"}
Make simple:
#GetMapping("/health")
public ResponseEntity<String> healthCheck() {
LOG.info("REST request health check");
return new ResponseEntity<>("{\"status\" : \"UP\"}", HttpStatus.OK);
}
Add produces = "application/json" in #RequestMapping annotation like:
#RequestMapping(value = "api/login", method = RequestMethod.GET, produces = "application/json")
Hint: As a return value, i recommend to use ResponseEntity<List<T>> type. Because the produced data in JSON body need to be an array or an object according to its specifications, rather than a single simple string. It may causes problems sometimes (e.g. Observables in Angular2).
Difference:
returned String as json: "example"
returned List<String> as json: ["example"]
Add #ResponseBody annotation, which will write return data in output stream.
This issue has driven me mad: Spring is such a potent tool and yet, such a simple thing as writing an output String as JSON seems impossible without ugly hacks.
My solution (in Kotlin) that I find the least intrusive and most transparent is to use a controller advice and check whether the request went to a particular set of endpoints (REST API typically since we most often want to return ALL answers from here as JSON and not make specializations in the frontend based on whether the returned data is a plain string ("Don't do JSON deserialization!") or something else ("Do JSON deserialization!")). The positive aspect of this is that the controller remains the same and without hacks.
The supports method makes sure that all requests that were handled by the StringHttpMessageConverter(e.g. the converter that handles the output of all controllers that return plain strings) are processed and in the beforeBodyWrite method, we control in which cases we want to interrupt and convert the output to JSON (and modify headers accordingly).
#ControllerAdvice
class StringToJsonAdvice(val ob: ObjectMapper) : ResponseBodyAdvice<Any?> {
override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean =
converterType === StringHttpMessageConverter::class.java
override fun beforeBodyWrite(
body: Any?,
returnType: MethodParameter,
selectedContentType: MediaType,
selectedConverterType: Class<out HttpMessageConverter<*>>,
request: ServerHttpRequest,
response: ServerHttpResponse
): Any? {
return if (request.uri.path.contains("api")) {
response.getHeaders().contentType = MediaType.APPLICATION_JSON
ob.writeValueAsString(body)
} else body
}
}
I hope in the future that we will get a simple annotation in which we can override which HttpMessageConverter should be used for the output.
Simple and Straightforward send any object or return simple List
#GetMapping("/response2")
#ResponseStatus(HttpStatus.CONFLICT)
#ResponseBody List<String> Response2() {
List<String> response = new ArrayList<>(Arrays.asList("Response2"));
return response;
}
I have added HttpStatus.CONFLICT as Random response to show how to pass RequestBody also the HttpStatus
Annotate your method with the #ResponseBody annotation to tell spring you are not trying to render a view and simple return the string plain
How can I easily separate JSON values that are sent in the same request?
Given that I POST a JSON to my server:
{"first":"A","second":"B"}
If I implement the following method in the Controller:
#RequestMapping(value = "/path", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public void handleRequest(#RequestBody String input) {
// ...
}
then the input parameter will constitute a String with the entire JSON object, {"first":"A","second":"B"}. What I really want is two separate Strings (or a String and an int whichever is suitable for the particular request) with just the two values (other key / value pairs that the client may send should be ignored).
If the strings were sent as request parameters instead of JSON request body it would be simple:
#RequestMapping(value = "/path", method = RequestMethod.POST)
public void handleRequest(#RequestParam("first") String first,
#RequestParam("second") String second) {
// ...
}
I know that I can create a simple bean class that can be used in conjunction with the #RequestBody annotation that will contain both A and B when used, but it seems like a detour, since they will have different purposes inside the web app.
Dependencies:
org.springframework : spring-web : 3.1.0.RELEASE
org.codehaus.jackson : jackson-mapper-asl : 1.9.3
POJO
public class Input {
private String first;
private String second;
//getters/setters
}
...and then:
public void handleRequest(#RequestBody Input input)
In this case you need Jackson to be available on the CLASSPATH.
Map
public void handleRequest(#RequestBody Map<String, String> input)
I have written a custom WebArgumentResolver that does exactly this, combined with a custom annotation.
I don't have the source available to me now, but basically I annotated my method like this:
#RequestMapping(value = "/path", method = RequestMethod.POST)
public void handleRequest(#JsonField("first") String first, #JsonField("second") String second) {
// ...
}
Then my JsonFieldWebArgumentResolver checks if the method parameter is annotated with JsonField, and if it is it extracts the actual type from the parameter (not quite straight-forward it turns out if you want to handle generic parameters as well, such as List<String> or List<Pojo>), and invokes Jackson's JsonParser manually to create the correct type. It's a shame I can't show you any code, but that's the gist of it.
However, that solution is for Spring MVC 3.0, and if you are using 3.1 I think you will be better off using a custom HandlerMethodArgumentResolver instead. But the idea should be the same.
I'm running a webapp in Spring Web MVC 3.0 and I have a number of controller methods whose signatures are roughly as follows:
#RequestMapping(value = "/{level1}/{level2}/foo", method = RequestMethod.POST)
public ModelAndView createFoo(#PathVariable long level1,
#PathVariable long level2,
#RequestParam("foo_name") String fooname,
#RequestParam(value = "description", required = false) String description);
I'd like to add some validation - for example, description should be limited to a certain length or fooname should only contain certain characters. If this validation fails, I want to return a message to the user rather than just throw some unchecked exception (which would happen anyway if I let the data percolate down to the DAO layer). I'm aware of JSR303 but have not worked with it and don't quite understand how to apply it in a Spring context.
From what I understand, another option would be to bind the #RequestBody to an entire domain object and add validation constraints there, but currently my code is set up to accept individual parameters as shown above.
What is the most straightforward way to apply validation to input parameters using this approach?
This seems to be possible now (tried with Spring 4.1.2), see https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/
Extract from above page:
Add MethodValidationPostProcessor to Spring #Configuration class:
#Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
Add #Validated to controller class
Use #Size just before #RequestParam
#RequestMapping("/hi")
public String sayHi(#Size(max = 10, message = "name should at most 10 characters long") #RequestParam("name") String name) {
return "Hi " + name;
}
Handle ConstraintViolationException in an #ExceptionHandler method
There's nothing built in to do that, not yet anyway. With the current release versions you will still need to use the WebDataBinder to bind your parameters onto an object if you want automagic validation. It's worth learning to do if you're using SpringMVC, even if it's not your first choice for this task.
It looks something like this:
public ModelAndView createFoo(#PathVariable long level1,
#PathVariable long level2,
#Valid #ModelAttribute() FooWrapper fooWrapper,
BindingResult errors) {
if (errors.hasErrors() {
//handle errors, can just return if using Spring form:error tags.
}
}
public static class FooWrapper {
#NotNull
#Size(max=32)
private String fooName;
private String description;
//getset
}
If you have Hibernate Validator 4 or later on your classpath and use the default dispatcher setup it should "Just work."
Editing since the comments were getting kind of large:
Any Object that's in your method signature that's not one of the 'expected' ones Spring knows how to inject, such as HttpRequest, ModelMap, etc, will get data bound. This is accomplished for simple cases just by matching the request param names against bean property names and calling setters. The #ModelAttribute there is just a personal style thing, in this case it isn't doing anything. The JSR-303 integration with the #Valid on a method parameter wires in through the WebDataBinder. If you use #RequestBody, you're using an object marshaller based on the content type spring determines for the request body (usually just from the http header.) The dispatcher servlet (AnnotationMethodHandlerAdapter really) doesn't have a way to 'flip the validation switch' for any arbitrary marshaller. It just passes the web request content along to the message converter and gets back a Object. No BindingResult object is generated, so there's nowhere to set the Errors anyway.
You can still just inject your validator into the controller and run it on the object you get, it just doesn't have the magic integration with the #Valid on the request parameter populating the BindingResult for you.
If you have multiple request parameters that need to be validated (with Http GET or POST). You might as well create a custom model class and use #Valid along with #ModelAttribute to validate the parameters. This way you can use Hibernate Validator or javax.validator api to validate the params. It goes something like this:
Request Method:
#RequestMapping(value="/doSomething", method=RequestMethod.GET)
public Model dosomething(#Valid #ModelAttribute ModelRequest modelRequest, BindingResult result, Model model) {
if (result.hasErrors()) {
throw new SomeException("invalid request params");
}
//to access the request params
modelRequest.getFirstParam();
modelRequest.getSecondParam();
...
}
ModelRequest class:
class ModelRequest {
#NotNull
private String firstParam;
#Size(min = 1, max = 10, message = "You messed up!")
private String secondParam;
//Setters and getters
public void setFirstParam (String firstParam) {
this.firstParam = firstParam;
}
public String getFirstParam() {
return firstParam;
}
...
}
Hope that helps.