0

I am developing Rest Apis using Spring mvc 5.0.8 and jackson 2.9.8

I want to set default pagination against every request, if pagination property is not present in client's json request.

I am achieving that by creating Pagination object from HttpRequestEntity class constructor,but If pagination request is present in json request,then jackson creating one more Pagination object by calling default constructor of Pagination class before calling setter method(setPagination(Pagination pagination)) of HttpRequestEntity class.

JackSon neither will create property object nor will hit the property setter method,if property is not present in JSON request

I also tried this one using Interceptor prepreHandle

request.setAttribute("pagination", new Pagination());

But that will not update HttpServletRequest's body,I have to receive that property with Controller's parameter which should be annotated with @RequestAttribute.

As per my under standing HttpMessageConverter only maps HttpServletRequest body with spring annotation @RequestBody.

Json Request

{
   //not sending pagination
   /*
   "pagination":{
      "offset":0,
      "limit:50
    },
    */
    "data":{
        "requestUrl":"some value"
        ...
    },
    "timeStamp":"Mon Sep 23 2019 02:15:47 GMT+0530 (India Standard Time)"
}

Controller

@RestController
@RequestMapping("/api/v1")
public class LocaldbController {

    @Autowired
    private LocaldbService localdbService;

    @PostMapping("/apidetails/filter")
    public void getAllApiDetails(@RequestBody HttpRequestEntity<ApiDetailsFilterDto> requestEntityDto) {

        System.out.println(requestEntityDto.getPagination().getLimit());
    }
}
public class HttpRequestEntity<T> {

    public Pagination pagination;
    private T data;
    private String timeStamp;

    public HttpRequestEntity() {
        this.pagination = new Pagination(); //To set Default value
    }

    public Pagination getPagination() {
        return pagination;
    }
    public T getData() {
        return data;
    }
    public String getTimeStamp() {
        return timeStamp;
    }
    public void setTimeStamp(String timeStamp) {
        this.timeStamp = timeStamp;
    }

    public void setPagination(Pagination pagination) {
        this.pagination = pagination;
    }

}
public class Pagination {

    private int offset = 0;
    private int limit = 50;

    public Pagination() {
        System.out.println("pagination");
    }

    public int getOffset() {
        return offset;
    }
    public int getLimit() {
        return limit;
    }

    public void setOffset(int offset) {
        this.offset = offset;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }
}

So anyone can tell me,how to set Default values to Properties if properties are not present in JSON request.

Thanks for your attention. I’m looking forward to your reply.

Saptarsi
  • 796
  • 5
  • 13
  • Check this question: https://stackoverflow.com/questions/18805455/setting-default-values-to-null-fields-when-mapping-with-jackson – Lucas Piske Sep 22 '19 at 20:48

2 Answers2

0

I don't exactly know what is the logic behind request deserialization, but I may suggest that you moved the new Pagination() invocation from constructor to the field declaration, as the logic from the constructor may not be invoked if some Java reflection magic happens.

public class HttpRequestEntity<T> {

    public Pagination pagination = new Pagination();
    ...

Another thing I'd like to point out is that you shouldn't worry about redundant object creation, because mechanisms like garbage collector exist just for the sole purpose of not having to worry about memory management.

EDIT:
Ok, I see that you're stubborn to check if pagination was sent or not. If you need to check for this, you're doing something wrong, because default data should indicate the default behaviour (default logic) and should NOT block your logic in any way.

You shouldn't also worry that the default object will be created every time, because Java's memory management is really efficient.

But if you really want to check whether Pagination is a default value or was actually sent by a client, use a decorator pattern.

public class HttpRequestEntity<T> {

    public Pagination pagination = new DefaultPagination();
    ...
}

public final class DefaultPagination extends Pagination {
    public DefaultPagination() {
        super();
    }

    @Override
    public void setOffset(int offset) {
        throw new IllegalStateException("Default pagination's state change not allowed");
    }

    @Override
    public void setLimit(int limit) {
        throw new IllegalStateException("Default pagination's state change not allowed");
    }
}

Then you can check if pagination is instanceOf DefaultPagination

multicatch
  • 192
  • 4
  • I have checked that **HttpRequestEntity** class object is being created by calling it's default constructor – Saptarsi Sep 22 '19 at 21:15
  • It would be more convenient if I could check before that pagination object is created or not,and if not then I would like to create default object – Saptarsi Sep 22 '19 at 21:17
  • Why would you need to check for that if the default object will be replaced with the actual data? – multicatch Sep 22 '19 at 21:23
  • See I am fulfilling my requirements by implementing the above code,but I want know if there is any other best possible option to do it.It would be great If I can manage that from Interceptor's **preHandle**,because Interceptor can do it before reaching to controller.And thanks for your reply. – Saptarsi Sep 22 '19 at 21:37
  • Yes that I can do.This is the better approach that what I am doing.Thank you again. – Saptarsi Sep 22 '19 at 21:45
0

If u want to create an object from constructor from pagination again check on setter Pagination method

public void setPagination(Pagination pagination) {
If(this.pagination!=null)
this.pagination==null//contructor object set to null
        this.pagination = pagination;
    }

}

I don't know your actual requirements why not create on fly object of pagination. Check if get Pagination is null create a pagination object. Create a service class and invoked the service class from controller to get your data, that service class check all the data accordingly create the pagination object on fly if it's null mean if Jackson will not hit the setter method... Might be it can help...

Sourav
  • 9
  • 2