Named Parameters rather than positional for Spring MessageSource.getMessage() - spring

we are using Spring MessageSource to build error messages in our app.
We populate our error messages like this
dobInvalid = The DOB supplied {0} is invalid
We want to use named parameters so we can do
dobInvalid = The DOB supplied {dob} is invalid
Looking in the Api docs for getMessage it appears to suggest you can do this
http://static.springsource.org/spring/docs/1.2.x/api/org/springframework/context/MessageSource.html
args - Array of arguments that will be filled in for params within the
message (params look like "{0}", "{1,date}", "{2,time}" within a
message), or null if none.
Obviously we can write our own but was wondering if spring can do it and if anyone can provide an example or using named parameters rather positional parameters.
Cheers
Mark

AIUI, Spring MessageSource works with JDK MessageFormat, so there is no such a named parameter. {1,date} is an example, where "date" refers to formatType, no to an arbitrary named parameter.
The general form of a parameter is:
{ ArgumentIndex , FormatType , FormatStyle }

Related

violation : Number of parameters should be limited - spring boot

I'm working in a spring boot application, where i'm getting violation as, "number of parameters should be less than 8"
i,m passing all the parameters through request param
I'm passing exactly 8 parameters all are mandatory
any other way to overcome this ?
In general, it looks like bad API design that you have so many request params. Request params are normally only used for things like filter and sorting options, but not to provide any actual data. Instead, use the request body.
Nevertheless, you can also get all parameters as a HashMap using:
#PostMapping("/api/example")
#ResponseBody
public String examplePost(#RequestParam Map<String,String> allParams) {
return "Parameters are " + allParams.entrySet();
}

#RequestHeader required property behavior for request paramter and value

Can we make a header parameter mandatory but not the value using #RequestHeader?
For example if we use,
#RequestHeader(value = "abc", required = true)
both parameter and it value has to be there.
Edit:
Suppose i call some rest api has above request header param with "abc" but no value. So in this case i am able to invoke the rest api successfully since i have invoke with "abc" header param even i did not enter a value to it. Due to some governance tool rule, i need to have a specific header param but i dont want force user to enter any value.
Spring 5.2 and lower
The #RequestHeader doesn't provide additional facility to check the value of the parameter to be mandatory i.e. not null.
Given below are the available fields as per Spring Doc
defaultValue: The default value to use as a fallback.
name: The name of the request header to bind to.
required: Whether the header is required; null values are allowed
value: Alias for name()
So what you can do is read the parameter either with the help of #RequestHeader or inject a HttpServletRequest request, read by request.getHeader(...) and check inside the controller method if the value exists and then can call methods to perform the necessary logic.
Although you can make sure that the parameter exists with the help of required attribute for e.g. #RequestHeader(value = "Authorization", required = true) String authorization).
Spring 5.3+
The required field was tightened up, both the property and the value should exist. From the release notes:
The #RequestHeader annotation detect a null conversion result value and treat it as missing. In order to allow an empty value to be injected as a null argument, either set required=false on the argument annotation, e.g. #RequestParam(required=false), or declare the argument as #Nullable.
As #Mudassar said, #RequestHeader doesn't provide additional facility to check the value of the parameter to be mandatory i.e. not null.
It is related to this issue: https://github.com/spring-projects/spring-framework/issues/23939
I developed a workaround for this problem using an annotation #RequestHeaderNonNull that I've created: https://github.com/armandoalmeida/request-header-required-non-null
I hope I've helped you!

Passing extra parameter through GetAll method of webapi

How to pass an extra parameter through a Get method of webapi because when i pass
GetALL(int page,int limit,int start) it works fine but when in passed one more parameters that is optional and may be null it throws error.
GetAll(int page,int limit,int start,string ? search)
What is the best way to make it working
In Web API optional parameters are those which can be nulled.
If you have type values like int or DateTime, you need to make them nullableby using the ? syntax.
But when they're classes instead of value type, they are directly convertible to null, so you don't need to, and can not, mark them as nullable. SO, your method signature must be simply this:
GetAll(int page,int limit,int start,string search)
If you wanted page, limit or start to be nullable, you should declare them as int?. So, int he signature above this 3 parameters are compulsory, and the last one optional.
EDIT, for OP comment
When you use the default routing for Web API the only way to choose the right method is by parameter matching, i.e. the parameters in the request must match the parameters in the action including the optional parameters. So, there are two ways to make it work:
post the optional parameters as empty parameters. For your case, provided you're using the query string, include a &search= in the URL
modify the routes, so that the parameters are provided as route parameters, and define the search parameter as optional
You can also completely modify the web API routing by including the action in the route. In that case, you have to specify the action in the URLs to invoke the action, but the method can be chosen by action name (given by method name or Action attribute), and not by parameter matching. In that case you don't need to provide the optional parameters. It will work like MVC routing.

Difference between an error code and a message code as far as Spring validation is concerned?

I am in reference to the following method from BindingResult:
BindingResult.html#resolveMessageCodes(java.lang.String, java.lang.String)
I am trying to figure out the difference between an error code and a message code. Can someone please provide an example, especially one that would illustrate why there could be several message codes for a given error code?
Because web applications are internationalized, when you reject an object and want to have a message displayed for it, you don't use a hardcoded text because that will show the same no matter the language.
Instead, you specify an error code that later server as a key to retrieving the proper message from the bundles (and now the error code is a message code from the point of view of the method that must find the proper message text).
Your error code resolves to more message codes because Spring (based on the implementation) adds some additional ones for you. Here is a snippet from the Spring documentation:
[...] What error codes it registers is determined by the MessageCodesResolver that is used. By default, the DefaultMessageCodesResolver is used, which for example not only registers a message with the code you gave, but also messages that include the field name you passed to the reject method. So in case you reject a field using rejectValue("age", "too.darn.old"), apart from the too.darn.old code, Spring will also register too.darn.old.age and too.darn.old.age.int (so the first will include the field name and the second will include the type of the field); this is done as a convenience to aid developers in targeting error messages and suchlike. [...]
The last statement is the reason there are more message codes, to have control on the message that is displayed to the user, from a generic one (e.g. "Value required") to a more specific one given the context (e.g. "A value is required for field XXX").
The javadoc for DefaultMessageCodesResolver explains it further and gives an example:
For example, in case of code "typeMismatch", object name "user", field "age":
try "typeMismatch.user.age"
try "typeMismatch.age"
try "typeMismatch.int"
try "typeMismatch"
This resolution algorithm thus can be leveraged for example to show specific messages for binding errors like "required" and "typeMismatch":
at the object + field level ("age" field, but only on "user");
at the field level (all "age" fields, no matter which object name);
or at the general level (all fields, on any object).

Usage of #RequestParam throws error in Spring 3

I am using the #RequestParam annotation to get the request parameters , and using the same to insert the values into the DB.
I have setup the controller to re-direct to the same page which contains the text fields for the user to enter the values, which are being read using the #RequestParam annotation.
But after I enter the values into the text fields , and click submit , it throws this error
Request processing failed; nested exception is java.lang.IllegalArgumentException: Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
I am a newbie to Spring 3 , and unable to understand the error. Can anybody please shed light on the same.
Thanks in advance,
Vivek
In order to inject the value of request parameter into your handler method parameter, either one of the following should be satisfied
The name of the request parameter must match the name of the method parameter.
e.g.
Following will inject the request parameter named "studentName" into the method parameter studentName
public String goToStep(#RequestParam String studentName)
The request parameter name must be explicitly specified if it does not match the method parameter. The following will inject "nameOfStudent" request parameter into studentName:
public String goToStep(#RequestParam("nameOfStudent") String studentName)
Please post your handler method code if your issue continues to persist.
I asked for the version you are using because I ran with a similar problem a few days ago. I was using Spring 3.1.0.M2 and the same exception appeared when I was using #PathVariable in proxied #Controller.
It was caused by a resolved known bug. You just have to switch to 3.0.6 or try the nightly build 3.1.0.BUILD-SNAPSHOT. Of course, the latter option is not recommended for production environment.

Resources