How to send model attribute to spring controller - spring

I want to test my controller using postman but don't know how to send a model attribute using postman. I even don't know whether it is possible or not.
My Controller seems like:
#Controller
#RequestMapping(path = "/api/v1")
public class PaymentController {
#Autowired
private CredentialsRepository credentialsRepository;
#PostMapping(path = "/charge")
public String charge(#ModelAttribute("pay-load") PayLoad payLoad, Model model) {
Credentials creds = credentialsRepository.findCredentialsById(1);
if (creds == null)
return "init_credentials";
return "charge";
}
}
Model Attribute
public class PayLoad {
private Integer mId;
private Integer ordId;
private Integer cardId;
private Integer cvvNo;
private String hash;
// getter & setter
}

I found the way to send model attributes to the spring controller.
see above screenshot for your reference.

Even you can pass all the key and value in requestParam from postman.
Instead of requestBody. ModelAttribute object treat each and every key and value as requestParam. It's just a way to combine a lot of requestParam in one object. Even you can try out with curl request, so it will make you more clear.
Thanks

Related

Validatng enums in Spring validation

I'm doing request parameter validation from a Spring controller. I have an Enum validator, similar to https://funofprograming.wordpress.com/2016/09/29/java-enum-validator/, which works fine if the enum field is directly in the object I'm using for validation. But it doesn't work if that object contains other objects.
For example, here is the request in the Controller
#PostMapping("/")
public ResponseEntity<?> performOperation(#Valid #RequestBody MyModel model) {
Here is the model I'm using to validate the request params
#ApiModel
public class MyModel {
#ApiModelProperty
#EnumValueValidator(enumClass = EnumName.class)
public String provider;
MyObject obj;
}
public class MyObject {
#EnumValueValidator(enumClass = SomeEnum.class)
public String anotherEnum;
}
In the above example, provider is validated with no problem. But anotherEnum is not. Is there a way for a Spring model to do a deep validation into objects?
You should annotate MyObject obj with #Valid annotation as well. Just keep in mind that null objects are not validated, so probably you should do both:
#NotNull
#Valid
MyObject obj;

DTO has only null with GET request params, but not POST #RequestBody

I'm trying to get my query params in a DTO like in this question but my DTO has always null value.
Is there anything wrong in my code ? I made it as simple as possible.
Queries:
GET http://localhost:8080/api/test?a=azaz => null
POST http://localhost:8080/api/test with {"a":"azaz"} => "azaz"
Controller with a GET and a POST:
#RestController
#RequestMapping(path = {"/api"}, produces = APPLICATION_JSON_VALUE)
public class MyController {
// GET: dto NOT populated from query params "?a=azaz"
#RequestMapping(method = GET, path = "test")
public #ResponseBody String test(TestDto testDto){
return testDto.toString(); // null
}
// POST: dto WELL populated from body json {"a"="azaz"}
#RequestMapping(method = POST, path = "test")
public #ResponseBody String postTest(#RequestBody TestDto testDto){
return testDto.toString(); // "azaz"
}
}
DTO:
public class TestDto {
public String a;
#Override
public String toString() {
return a;
}
}
Thanks !
Full Spring boot sample to illustrate it
The problem is that you are missing setter for the field.
public void setA(String a) {
this.a = a;
}
should fix it.
I'm assuming that you have done required configuration like having Jackson mapper in the class path, consume json attribute, getter and setter in DTO classes etc.
One thing missed here is, in RequestMapping use value attribute instead of path attribute as shown below
#RequestMapping(method = POST, value= "/test", consumes="application/json")
public #ResponseBody String postTest(#RequestBody TestDto testDto){
return testDto.toString();
}
And, make sure that you set content-type="application/json" while sending the request
I think what you are trying to do is not possible. To access the query Parameter you have to use #RequestParam("a"). Then you just get the String. To get your object this way you have to pass json as Parameter. a={"a":"azaz"}
Kind regards

Map #CookieValue, #RequestHeader etc. to POJO in Spring Controller

I have a bunch of params in my controller and want to map all of them to a separate POJO to keep readability. There is also a #CookieValue, #RequestHeader I need to evaluate and aim for a solution to also map them to that POJO. But how?
I saw a possible solution on a blog but it doesn't work, the variable stays null.
Controller:
#RequestMapping(path = MAPPING_LANGUAGE + "/category", produces = MediaType.TEXT_HTML_VALUE)
#ResponseBody
public String category(CategoryViewResolveModel model) {
doSomething();
}
And my POJO is this:
public class CategoryViewResolveModel {
private String pageLayoutCookieValue;
public CategoryViewResolveModel() {
}
public CategoryViewResolveModel(
#CookieValue(value = "SOME_COOKIE", required = false) String pageLayoutCookieValue) {
this.pageLayoutCookieValue = pageLayoutCookieValue;
}
... some other RequestParams, PathVariables etc.
}
According to the documentation it's not possible for #CookieValue and #RequestHeader.
This annotation is supported for annotated handler methods in Servlet
and Portlet environments.
Take a look at:
https://www.petrikainulainen.net/programming/spring-framework/spring-from-the-trenches-creating-a-custom-handlermethodargumentresolver/
instead of using getParameter to access request parameters you can use getHeader to retrieve the header value and so define your CategoryViewResolveModel just as you were requesting

Spring MVC parse web url Object

I have a GET request in the format below
http://www.example.com/companies?filters=%7B%22q%22%3A%22aaa%22%7D
After decode it is
filters={"q":"aaa"}
I have created an Object named Filters as below
public class Filters {
private String q;
//getter setter....
}
and in my controller
#RequestMapping(method = RequestMethod.GET)
public List<CompanyDTO> getCompanies(Filters filters) {
filters.getQ();
//do things
}
However, the filters.getQ() is null.
Am I doing something incorrect here?
You need to associate the request parameter to the method argument. Add #RequestParam to your method i.e.
#RequestMapping(method = RequestMethod.GET)
public List<CompanyDTO> getCompanies(#RequestParam(value="filters") Filters filters) {
filters.getQ();
//do things
}
Instead of #RequestParam, use #RequestBody
Instead of String filters=%7B%22q%22%3A%22aaa%22%7D, pass JSON object as parameter http://www.example.com/companies?filters={"q":"aaa"}

From request object to the database

I have an app with an AngularJS front-end and a Spring MVC back-end. I'm having some trouble with converting/mapping request objects to domain/dto objects.
On one page you can add a new order to the system, the POST payload would look something like this:
{
memo: "This is some extra info for order",
orderLines: [{productId:3, quantity:4}, {productId:2, quantity:5}, {productId:1, quantity:4}],
shippingDate: "2014-10-08T19:16:19.947Z",
warehouseId: 2
}
The Spring MVC controller method looks like this:
#RequestMapping(value = "/order", method = RequestMethod.POST)
public ResponseEntity<Void> addOrder(#RequestBody #Valid OrderRequest orderRequest, UriComponentsBuilder b) throws Exception {
// the magic
}
Where OrderRequest is filled with the values of the POST request, the OrderRequest and OrderLineRequest look like this:
public class OrderRequest {
private Long id;
private Date shippingDate;
private String memo;
private List<OrderLineRequest> orderLines;
private Long warehouseId;
public OrderRequest() {
}
// getters and setters ommitted
}
public class OrderLineRequest {
private Long id;
private String productCode;
private int quantity;
public OrderLineRequest() {
}
}
My question now is, in order to save an Order object with orderService.add(order) I need to construct the Order object based on the values that were sent in the request. Where/how do I do this?
OPTION 1
The OrderRequest class could have a makeOrder() method with just returns an Order object like so:
public Order makeOrder() {
Order order = new Order();
order.setMemo(this.memo);
order.setShippingDate(this.shippingDate);
...
}
Then I'd have to map the OrderLineRequest which could have their own makeOrderLine method:
public OrderLine makeOrderLine() {
OrderLine orderLine = new OrderLine();
orderLine.setQuantity = this.quantity;
...what to do with only the productId?
}
As you can see I can set the quantity but in the request I only received the productId, but in the database I save the productCode, productName as well, so I need that info from the database, but I don't want to make a database call from the Request object...I also don't want to half of the mapping in the request object and the rest of the mapping in the controller where I do have access to the services.
OPTION 2
I can use Dozer to do the mapping for me, but that would mean injecting the services into the Dozer custom converters which seem equally unclean to me...
OPTION 3
I pass the OrderRequest object to the service layer and let the service layer handle it, but my question would remain, how exactly would the service layer convert it, say you have the method addOrder like this:
public void addOrder(OrderRequest orderRequest) {
}
Would you call another service to convert from one to the other as I don't really want this conversion in a business logic method?
Any help would be appreciated
use the #RequestBody to map your jsonObject that is send with the request , to a DTO .
please refer to the following tutorial .
hope that helps .
and please ask if there is something not clear .

Resources