Reputation: 1862
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
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
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