I have request like ...?abc=value and following rest implementation (Spring):
#GetMapping("/")
String getSth(Pojo pojo) {
...
}
where Pojo is
Pojo {
private String someOtherName;
//getters, setters
}
Is it possible to bind query param abc to class attribute someOtherName? I know, that if query param fits to pojo attribute, it works by default...
Does Spring support custom mappings between POJO attributes and query params?
Related
Can you manipulate properties (e.g. set null ones to Hello world) annotated with a custom annotation as they are handed over to methods in your controller?
For example, let's assume we have a nested DTO:
public class MyDto {
#MyAnnotation
private String myProperty;
private String unannotatedPropety;
private InnerEntity innerEntity;
// Getters and setters omitted for brevity
}
public class InnerEntity {
#MyAnnotation
private String anotherProperty;
// Getters and setters omitted for brevity
}
#RestController(...)
public class MyController {
#PostMapping(...)
public Mono<ResponseEntity<MyResponse>> myRequestHandler(#RequestBody Mono<MyEntity> json) {
// ..
}
}
I initially thought a ConditionalGenericConverter could do the trick (its signature allows for null values to be converted, and it provides TypeDescriptors for its source and target properties, making introspection a breeze), but for controllers, Spring actually uses HttpMessageConverter for payloads (kudos), it seems, and I didn't want to reinvent the entire Jackson deserializer.
On the other hand, Spring + Hibernate Validator manage to introspect payloads and check all properties for specific annotations, so getting to annotated properties should be possible, I hope...
I could probably use AspectJ, but I want this to work in general, and not rely on the payload being of a specific type (like MyDto)... I'm basically hoping there exists a hook I can use, just like the converters API, that does the heavy lifting of reflection for me...
Is there an (easy) approach to do what I want to do?
How the request body of form is passed to the spring MVC controller and how to map to the POJO class instance?
I presume, you are building end point using POST. If yes, you can annotate method parameter with #RequestBody to a capture request body.
Basically, #RequestBody is used to bind the HTTP request body with a domain object in method parameter. Behind the scenes, these annotation uses HTTP Message converters to convert the body of HTTP request to domain objects.
#RequestMapping(value="/user/create", method=RequestMethod.POST)
public void createUser(#RequestBody User user){
// your logic goes here..
// Make sure that parameters in User POJO matches with HTTP Request Parameters.
}
I assume you are using POST API request for your use case. In the spring mvc controller class, we can make use of #RequestBody annotation followed by Pojo class.
Example:
#PostMapping
public ResponseEntity<ResponseDto> saveData(#RequestBody Data data) {
// Access to service layer
}
Let's say you're doing a POST request.
#PostMapping
public void saveSomeData(#RequestBody PojoClass pojoClass){
// whatever you wanna do
}
The #RequestBody annotation extracts the data your client application is sending on the body of the request. Also, you'd want to name the member variables on your pojo class similar to how you named it in on your request body.
Your POJO class can be something like:
public class PojoClass{
private String name;
private int age;
}
Now you can create getters and setters or use the Lombok annotation #Data on the class level to auto-generate the getters and setters.
Hope this was helpful:)
I want SpringBoot to be able to provide default values for fields that the user must enter. For example, I have something like this:
*Controller class*
#PostMapping("/test")
public ResponseEntity<> myMethod(#RequestBody #Valid MyContract contract) {}
*MyContract class*
#Valid
DataObject dataObject;
*DataObject class*
#Component
public class DataObject {
private #Value("${field1.default}") String field1Default;
private String field1
public String getField1() {
return (field1 == null ? field1Default : field1);
}
}
The DataObject class needs to be created on a per request basis. There are also other places in the code where it needs to be created on demand. So I imagine it needs to be a Prototype object. But I can't figure out how to get Spring to created it properly when it creates it for the request.
Update
I have read more about #RequstBody, e.g., https://www.javadevjournal.com/spring/spring-request-response-body/ and Should spring #RequestBody class be singleton or prototype?, which explains that the object is not a Component, but a simple POJO that gets the values from the Json request. So it seems that there is no way to inject #Values from the Spring application.properties file. Is there any other way around this? Or another suggested implementation?
Working with a vanilla #RestController in Spring.Boot, how can you use the default databinding and properly bind to nested Optional attributes in a data object?
In terms of code, this is the data class (using lombok to reduce the boilerplate)
#Data
public class SomeData {
Optional<String> name;
}
which is used as a request parameter in a GET route, like this
#GetMapping("/something")
public void getSomething(SomeData data) {
...
}
The problem: if no corresponding parameter is given in the request, then data.name is null instead of Optional.empty.
What I found so far:
* Optional is handled properly when you just use it directly, like getSomething(Optional<String> name)
* Additional annotations like #RequestParam or #Valid don't affect this behavior
I am doing a POST request to my Rest Contoller with the following object:
{
"relationship.name": "someting"
}
I'd like to map that to a POJO:
public class Request {
private String relationshipName;
// Getters, setter and contructor
}
How would I dot that?
Annotate your property with #JsonProperty
public class Request {
#JsonProperty("relationship.name")
private String relationshipName;
...
}
By default, the mapping will use the variable name as the key for the property. So without the annotation, it would expect relationshipName. #JsonProperty allows you to customize the key without changing the variable name.
Have u tried using #JsonProperty on relationshipName?
#JsonProperty(name), tells Jackson ObjectMapper to map the JSON property name to the annotated Java field's name.