Why am I able to use this annotation - give it a value without specifying which element I'm assigning this value to? For example, I can write: #RequestMapping("/home") instead of #RequestMapping(value="/home").
The specs do not mention anything about it. Is it just a behaviour of Java annotations treating the field value as default one?
Case #1: If you have a single value then it's optional to write like this:
#RequestMapping(value="/home")
In this case you may write
#RequestMapping("/home") also. While providing a single string this is automatically assigned to "value". [ default behavior ]
Case #2:
#RequestMapping has a String[] value parameter, so you should be able to specify multiple values like this:
#RequestMapping(value={"","/", "/away", "/home"})
Related
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.
Is it possible to pass Java code as a value in a YAML file. For example, something like this:
---
dueDate: "DueDateCalc()"
DueDateCalc() might be a method defined in the Java code that is parsing the YAML. It would then set the Java dueDate property to the return of the predefined DueDateCalc() method.
This is possible within the constraints of Java runtime reflection, however you need to implement it yourself.
For example, your YAML could look like this:
---
dueDate: !call DueDateCalc
!call is a local tag for telling the loading code that the scalar value DueDateCalc should be interpreted as method to be called (this is chosen by you, not something predefined). You can implement this with a custom constructor for the !calc tag that searches for a method with the given name within some given class, and then calls it on some given object.
What about parameters? Well, still possible, but will get ugly fast. First problem is how you define the paramaters:
with nested YAML sequences: !call [MyMethod, [1, 2, 3]]
with a scalar that needs to be parsed: !call MyMethod(1, 2, 3)
The former option lets YAML parse the parameters and you'll get a list; the latter option requires you to parse the method call yourself from the string you get from YAML.
The second problem is to load the values into Java variables so that you can give them as argument list. Java reflection lets you get the method's parameter types and you can use those to load the parameter values. For example, if the first parameter's type is a String, you would parse 1 as a "1", while if it's an int, you can parse 1 as int. This is possible with SnakeYAML's builtin facilities if you're using nested YAML sequences for method call encoding.
This would even work if parameters are class objects with complex structure, you'd just use normal YAML syntax and the objects will be loaded properly. Referring to variables in your code is not directly possible, but you could define another tag !lookup which retrieves values from a given Map structure.
While reflection lets you make method calls, you can not directly evaluate an expression like 6*9. So before you try and implement anything, evaluate which functionality you need and check whether it's doable via reflection.
I have an unusual use case.
In my left hand, I have a String value (say, "5001"). In my right hand I have an Annotation literal with some interesting information. It basically defines a named "slot" for which (in this example) "5001" is an appropriate value.
Let us now also say that I have some javax.validation.constraints Annotation (like Digits) in my...other hand. Note that I do not have any reference to any field or method or any other AnnotatedElement—just the javax.validation.constraints Annotation literal itself. This is the weird part, but take it as fact.
Armed with these bits, I can almost use ConstraintValidator to see if "5001" is a valid value for the "slot" defined by my annotation literal. But not quite, as I cannot acquire a ConstraintValidatorContext for use in the isValid() method.
(I have read this question on the subject, which suggests that I'm out of luck.)
I also cannot simply use the Validator API as I am not validating a bean instance but instead merely a value that, if everything goes well, may be used indirectly in an XSLT file, if you must know. :-) It's the determining if everything is going to go well part that I'd like to use javax.validation for here. But, as mentioned, I don't have a bean instance with an annotated element to validate—I just have the value that would go into that annotated element.
Is there a way forward here?
In some cases I have seen two different ways to specify uri in #RequestMapping:
#RequestMapping(value="/somepath")
#RequestMapping("/somepath")
The latter is often used at class level. So, is it always legal omitting the value attribute?
The Java Language Spec states
It is legal to use single-element annotations for annotation types with multiple elements, so long as one element is named value, and all other elements have default values.
Since #RequestMapping has a defined value attribute and all other attributes have default values (empty arrays), it is always legal to omit spelling the name value if you don't specify any other attributes for the annotation:
#RequestMapping("/somepath") // valid
#RequestMapping("/somepath", method = RequestMethod.GET) // INVALID!
For #RequestMapping annotation value is the primary attribute, it is mandatory.
1)#RequestMapping(value="/somepath"):
Here you can mention remaining attributes, for ex: method,produces
2) #RequestMapping("/somepath"):
Here you can not mention rest of the attributes, as by default "/somepath" will be taken as value attribute.
Check this
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.