Reputation: 536
I'm trying, without success, to manipulate some http parameters (in query, body ...) before the call is received by the final endpoint. For example, we have this post call:
curl -X POST "http://localhost:8080/insertBody/" -H "accept: application/json" -H "Content-Type: application/json" -H "Date-Format: yyyy-MM-dd" -d "{ \"isUniform\": true, \"myDate\": \"2020-01-14T08:55:07.013Z\", \"myInt\": 0, \"uniform\": true}"
What I'm trying to do is converting myDate -> 2020-01-14T08:55:07.013Z inside the post body in this format yyyy-MM-dd passed in the header. The manipulation has to involve all objects of type OffsetDateTime (in this case) present in this call.
When the call is received by the microservice:
Header:
Date-Format: yyyy-MM-dd
Body
{
"isUniform": true,
"myDate": "2020-01-14T08:55:07.013Z",
"myInt": 0,
"uniform": true
}
After data manipulation and what is received by the controller:
Header:
Date-Format: yyyy-MM-dd
Body
{
"isUniform": true,
"myDate": "2020-01-14", <---
"myInt": 0,
"uniform": true
}
Body class
public class CashBackCampaignRequest {
@JsonProperty("uniform")
private Boolean uniform = true;
@JsonProperty("myInt")
private Integer myInt = null;
@JsonProperty("myDate")
private OffsetDateTime myDate = null;
// getter setters ...
}
Upvotes: 0
Views: 1041
Reputation: 536
Based on RUARDO answere I canged RequestBodyAdviceAdapter with ResponseBodyAdvice< Object>
@ControllerAdvice
public class ResponseJsonFilterAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
// true if want to use this controller
return true;
}
@Override
public Object beforeBodyWrite(
Object body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response) {
List<String> headers = request.getHeaders().get("X-MY-DATE-FORMAT");
if(headers == null || headers.isEmpty())
return body;
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(OffsetDateTime.class, new JsonSerializer<OffsetDateTime>() {
@Override
public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeString(DateTimeFormatter.ofPattern(headers.get(0)).format(offsetDateTime));
}
});
objectMapper.registerModule(simpleModule);
try {
return objectMapper.writeValueAsString(body);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return body;
}
}
Upvotes: 0
Reputation: 2850
You should use the famous RequestBodyAdviceAdapter
. You can, before entering your controller, manipulate the body of your message. You declare a @ControllerAdvice
or @RestControllerAdvice
(it is just a @Component
), and extends the class RequestBodyAdviceAdapter
. (you can also implements the interface RequestBodyAdvice
, but I'd recommend extending the abstract class).
Here is a quick example:
@RestControllerAdvice
public class WebAdvice extends RequestBodyAdviceAdapter {
@Override
public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
// to know whether you will use your advice or not
return true;
}
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
String format = inputMessage.getHeaders().get("DATE_FORMAT").get(0);
if(body instanceof CashBackCampaignRequest) {
// Do whatever you want
((CashBackCampaignRequest) body).setDate()
}
return super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
}
Be careful with the type of the request received in the Controller
. If your controller receives an object of type CashBackCampaignRequest
, then you won't be able to change the format.
Upvotes: 1