Get value from #RequestParam without specified name - java

I know that if a parameter looks like this:
#RequestParam("userId") String userId
I can get the value by calling this:
requestParam.value()
But if I don't specify a name, Spring automatically uses the variable name. Like this:
#RequestParam String userId
If the param name isn't specified, how can I access it? I know its possible because Spring does it somehow, but requestParam.value() is blank in this case.

Spring doesn't populate the request based on the #RequestParam. Rather it populates the method argument annotated with #RequestParam (in a method annotated with #RequestMapping). The parameter given to the #RequestParam annotation tells Spring the name of the request parameter you want it to use as that argument. If you don't provide one, Spring defaults to using the name of the argument (so the 2 examples you give in your question are equivalent).
If you are trying to access a request parameter, you need to know the name of it, regardless of the framework you are using.

Recommend you not to do it that way.Spring use asm
to analysis the java bytecode file,and extract parameter name of a method.But some time this does not work,because some .class file does not comprise parameter name,just parameter types,it depends on compiler options.

In case of Java 8, Spring uses StandardReflectionParameterNameDiscoverer, which relies on Java 8 Parameters API.
For details how to set up parameters option and use it via reflection see this answer.

Just call userId, as in doSomething(userId). Spring binds everything up for you.

Related

Why do we need the annotation "RequestParam()"

I'm learning Spring Boot right now, I don't really understand why we need this annotation. In my opinion, this annotation is used to rename.
public String home(#RequestParam("name") String othername, HttpSession session){
session.setAttribute("name", othername);
return "home.jsp"
}
So if the above code is running, I can pass my name like this: http://127.0.0.1:8080/home?name=bob
But if I don't have the annotation, I can only do http://127.0.0.1:8080/home?othername=bob, why we don't just change the name of the parameter? I think I might misunderstand the concept of RequestParam.
If you only have a handful of request parameters with default behaviour and you can easily name them as you wish, then you are right, the RequestParam annotation is not strictly necessary. However, as soon as you add PathVariables in the mix, or a request parameter e.g. is not required anymore, but optional, you have to add the annotation there again. Handling the parameter names is just one small aspect of that annotation. Additionally, you might have to implement a legacy API, where the parameter names on the ReST API level cannot be changed, but you want to have a better name in your code for readability, clean code or other reasons.
You did not misunderstand the concept but your knowledge about it is limited.
It is correct that #RequestParam can be used to rename the request parameter. Why we don't just change the name of the parameter? What if you want to have a parameter name as "package", you cannot just change the variable name to package as it is java reserved keyword, but you can have it as #RequestParam(name = "package") String othername.
Renaming is just one use case of #RequestParam some of the other uses are:
Differentiates between #RequestParam and #PathVariable variables
Make a parameter optional with required attribute #RequestParam(required = false).
Add a default value for the request parameter #RequestParam(defaultValue = "test").
Better code readability.

How does Spring MVC convert #RequestParam values?

I'm new to the Spring Framework, and as a symptom, I want to keep my adoption of its Web MVC portions as simple as possible, so I'm using the annotation functions to work with Spring. In the past, I've used:
int value = Integer.valueOf(request.getParameter("numberValue")) to pull values from parameters - explicitly converting the String returned by getParameter(). Helpfully, I've noticed that when I use Spring's terminology:#RequestParameter("numberValue") int numVal
the conversion is handled automatically. This is nice, but a "black box" to me. I tried looking at questions on here or in the Spring documentation, but all that information deals with custom conversions (like Converter) for objects or formatting issues. All I want to know is how Spring handles primitive type conversions for #RequestParam by default.
I've noticed that when I use Spring's terminology:
#RequestParameter("numberValue") int numVal the conversion is handled
automatically.
Here you are looking for Type Conversion
As per spring documentation given on this link
String-based values extracted from the request including request
parameters, path variables, request headers, and cookie values may
need to be converted to the target type of the method parameter or
field (e.g., binding a request parameter to a field in an
#ModelAttribute parameter) they’re bound to. If the target type is not
String, Spring automatically converts to the appropriate type. All
simple types such as int, long, Date, etc. are supported.

Dynamically setting and getting bean properties in XPages

Just another Java problem (I'm a noob, I know): is it possible to use dynamic property binding in a Custom Control with a dynamic property getter in a Java bean?
I'll explain. I use this feature extensively in my Custom Controls:
<xp:inputTextarea id="DF_TiersM">
<xp:this.value><![CDATA[#{compositeData.dataSource[compositeData.fieldName]}]]></xp:this.value>
This is used in a control where both datasource and the name of the field are passed as parameters. This works, so far so good.
Now, in some cases, the datasource is a managed bean. When the above lines are interpreted, apparently code is generated to get or set the value of ... something. But what exactly?
I get this error: Error getting property 'SomeField' from bean of type com.sjef.AnyRecord which I guess is correct for there is no public getSomeField() in my bean. All properties are defined dynamically in the bean.
So how can I make XPages read the properties? Is there a universal getter (and setter) that allows me to use the name of a property as a parameter instead of the inclusion in a fixed method name? If XPages doesn't find getSomeField(), will it try something else instead, e.g. just get(String name) or so?
As always: I really appreciate your help and answers!
The way the binding works depends on whether or not your Java object implements a supported interface. If it doesn't (if it's just some random Java object), then any properties are treated as "bean-style" names, so that, if you want to call ".getSomeField()", then the binding would be like "#{obj.someField}" (or "#{obj['someField']}", or so forth).
If you want it to fall back to a common method, that's a job for either the DataObject or Map interfaces - Map is larger to implement, but is more standard (and you could inherit from AbstractMap if applicable), while DataObject is basically an XPages-ism but one I'm a big fan of (for reference, document data sources are DataObjects). Be warned, though: if you implement one of those, EL will only bind to the get or getValue method and will ignore normal setters and getters. If you want to use those when present, you'll have to write reflection code to do that (I recommend using Apache BeanUtils).
I have a post describing this in more detail on my blog: https://frostillic.us/f.nsf/posts/expanding-your-use-of-el-%28part-1%29

Distinguish empty value from empty string ("") in Url query parameter

How to distinguish URL without value like this /url?var from /url?var="" in Spring MVC?
Method HttpServletRequest::getParameterMap() in controller returns "" in both ways.
I need this to separate commands from queries to specified resource.
One simple way of going about doing what you want to is use the getQueryString() of HttpServletRequest. You would just check and see if the returned String contains the pattern you are looking for.
If you need something like that often (as in many controller methods) you could also easily create a custom HandlerMethodArgumentResolver that will indicate the presence of a String in the URL.
Here is the relevant Javadoc and here is an example
/url?var is a valid URL which states that you have a parameter var which is not initialized.
So by default it is initialized to empty string. That's the framework behavior.
If you don't want to see that parameter coming in HttpServletRequest::getParameterMap(), just don't use it with URL (i.e. /url should be your call)

Validate Numbers in Spring

I have a basic doubt in how to proceed in my application. I have a form and I need to validate that all the inputs which are numbers. I have a problem in deciding the type of the attributes of the bean asociated with the form. I don't know if setting them to String or to double and here are the reasons:
If I set them to double: If I enter in the input something which is not a number when spring populates the inputs into the bean I get an Exception in the JSP that it could not convert it into double.
If I set them to String: I have a good validation although I have to change them later to double. But my problem here is that this bean is stored in a database with hibernate and the annotation #column would store it as a text and I would like to store it as if it were a double. Is there any posibility to change the column type to the double deferred type?
Does anyone can give me any idea in how to preceed in this case?
Thanks.
I suggest you always work with your domain types and not use String just because that's the way HTTP sends params. If a field has type double, you will use it as such in your code and also store it as such in the database. Let Spring convert the request params to your needed type.
Data binding is useful for allowing user input to be dynamically bound to the domain model of an application (or whatever objects you use to process user input). Spring provides the so-called DataBinder class to do exactly that.
You can register those in the initBinder method of your controllers and will allow you to transform the Strings from your request into the desired type. See for example the CustomNumberEditor class used to parse user-entered number strings into Number properties of beans. You can then combine this with the Validator interface for more complex checks.
EDIT: Spring binding uses typeMismatch error codes for binding errors when a conversion fails (required code if you specify a field as required but you don’t supply it). In your case it defaults to showing the exception message. To change the message to a more friendly one, you must supply a bundle key in your property file using the typeMismatch prefix.
This is specified by the DataBinder.setMessageCodesResolver and defaults to org.springframework.validation.DefaultMessageCodesResolver. In the javadoc of DefaultMessageCodesResolver you can see complete examples, but basically, you just have to add an entry like this in your properties file:
typeMismatch.yourField=Your user friendly error message goes here
You can map the exception to the custom message if you have an entry in the following form in your message.properties (or the equivalent message bundle that you are using).
typeMismatch.fieldName, where fieldName would be the name of the field you are validating.
If you are using Spring 3.0
have a look at the Overriding Defaults with Annotations part of
Spring 3 Type Conversion and Validation
If you are using Spring 2.x+ you can achieve this by registering Custom PropertyEditor as mentioned in above post

Categories