mallikarjun
mallikarjun

Reputation: 1862

Parse headers information and set it in bean

In my spring rest application I need to read the headers information for PUT and POST calls and set those information in the bean passed as @RequestBody. currently what am doing is like follows.

@RequestMapping(value = "/create", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public ReportRepresentation createDailyReport(@RequestBody ReportEntity reportEntity,
        @RequestHeader(value= "FIRST_HEAD1", required  = false) boolean isHeaderSet,
        @RequestHeader(value= "SECOND_HEAD2", required  = false) Long scondHead) {
            // Setting the header values into bean properties .
}

So am extracting the headers in all methods(POST and PUT) and setting values in different entities.

My question is is there any way to parse/ override the @RequestBody in method param in global level and set those headers?

Upvotes: 3

Views: 3154

Answers (2)

mallikarjun
mallikarjun

Reputation: 1862

I have implemented the same as @caco3 mentioned here is my implementation with set the values to bean.

 @ControllerAdvice
 public class RequestBodyAdviceChain implements RequestBodyAdvice {

 .. Other methods
 @Override
 public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
        Class<? extends HttpMessageConverter<?>> converterType) {

    HttpHeaders headers = inputMessage.getHeaders();

    List<String> emulated = headers.get("FIRST_HEAD1");
    Boolean isEmulated = false;
    Long emulatedUserId = null;
    if (!CollectionUtils.isEmpty(emulated)) {
        isEmulated = Boolean.valueOf(emulated.get(0));
    }

    if (isEmulated) {
        List<String> users = headers.get("SECOND_HEAD2");

        if (!CollectionUtils.isEmpty(users)) {
            emulatedUserId = Long.valueOf(users.get(0));
        }
    }

    if (isEmulated) {
        if (setField(body, Is_Emulated_Field, isEmulated)) {
            setField(body, EmulatedUserId_FIELD, emulatedUserId);
        }
    }

    return body;
 }

/**
 * <p>
 * Method to set the field value for the emulated user and it's id wven
 * though if the fields are defined in the super class.
 */
private static boolean setField(Object targetObject, String fieldName, Object fieldValue) {
    Field field;
    try {
        field = targetObject.getClass().getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
        field = null;
    }
    Class superClass = targetObject.getClass().getSuperclass();
    while (field == null && superClass != null) {
        try {
            field = superClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            superClass = superClass.getSuperclass();
        }
    }
    if (field == null) {
        return false;
    }
    field.setAccessible(true);
    try {
        field.set(targetObject, fieldValue);
        return true;
    } catch (IllegalAccessException e) {
        return false;
    }
}
}

Upvotes: 1

Denis Zavedeev
Denis Zavedeev

Reputation: 8307

You can use RequestBodyAdvice:

For example:

Bean:

@Data
public class MyBean {
  private String property;
}

Controller:

@RestController
public class MyController {
  @RequestMapping("/")
  public MyBean get(@RequestBody MyBean myBean) {
    return myBean;
  }
}

Advisor:

@ControllerAdvice(annotations = RestController.class)
public class MyRequestBodyAdvisor extends RequestBodyAdviceAdapter {
  @Override
  public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
    return methodParameter.getParameterType() == MyBean.class;
  }

  @Override
  public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
    MyBean myBean = (MyBean)body;
    List<String> strings = inputMessage.getHeaders().get("X-Property");
    myBean.setProperty(strings.get(0));
    return myBean;
  }
}

Testing:

$ curl localhost:8080 -d '{}' -X POST -H 'X-Property: myProp' -H 'Content-Type: application/json' -s

Output: {"property":"myProp"}

Upvotes: 2

Related Questions