How to add support for Shallow ETag in ResponseEntity Spring Java - spring

I understand that we can create the filter for Shallow E tag in spring. However, i am looking if there is an easier way to do it.
I am using HttpEntity in my code for getting the response.
The code looks like this
return ResponseEntity.ok()
.eTag(getETag(preloadMap))
.body(preloadMap);
However, I am looking forward to options of changing this etag to Shallow etag in a simpler way.

I think using spring filter is the easiest way to implement shallow etag. Within three lines it's done.
#Configuration
public MyConfigClass () {
#Bean
public Filter shallowEtagHeaderFilter() {
return new ShallowEtagHeaderFilter();
}
}
This filter is in charge of generating a hash response and adding it up to the etag header.
It also verifies if the created hash matches with the existing etag from "if-none-match". If both are equal it returns 304 Not modified. Otherwise it just returns 200 OK.

Related

spring cloud gateway, avoid routing to a uri

I'm looking for a way to execute some filters and predicates on a request, and at the end simply return a response to the user, instead of routing it to a specific URI.
For example, a user is calling /auth/token and my gateway has a filter that generates a token and transforms the body of the response (using the ModifyResponseBodyGatewayFilterFactory).
When adding a filter that simply returns response.setCompleted(), the body returns empty and the status code is always 200.
return (exchange, chain) -> {
return modifyResponseBodyGatewayFilterFactory.apply(c -> c.setRewriteFunction(Object.class, String.class, SomeBody))
.filter(exchange, chain)
.then(exchange.getResponse().setComplete());
}
How can I return a specific body to the user, without routing to a URI?
Thanks in advance!
I couldn't find a solution, so instead, I've created a web flux controller for this specific request.
This is a good enough solution for me.

ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) showing inconsistency across the classes while using WebClient

I have started using WebClient(org.springframework.web.reactive.function.client.WebClient) for calling rest services. I have 2 classes say Utility.java and ServiceImpl.java.
ServiceImpl.java is where I use WebClient. A post call I am making looks like -
ClientResponse response = webClient.post()
.uri(path)
.body(Mono.just(inputDTO),InputDTO.class)
.exchange()
.block();
(ClientResponse above is org.springframework.web.reactive.function.client.ClientResponse)
(I am using exchange instaed of retrive because I want headers as well as status code)
Now trying to convert this response into some DTO - ResponseDTO.
Mono<ResponseEntity<ResponseDTO>> mono = response.toEntity(ResponseDTO.class);
ResponseEntity<ResponseDTO> resEntity = mono.block();
ResponseDTO myObj = resEntity.getBody();
So myObj is an object of ResponseDTO class.
The issue is - when I perform the conversion of 'response into ResponseDTO.java' in my utility class, I get myObj = null. But if I do it in my ServiceImpl.java (just after calling post API), it returns the proper body (ResponseDTO object).
The same issue occurs even if I perform the conversion and post call operation in two different methods in the ServiceImpl.java.
Do I need to configure something here?
I figured out what was the issue.
After calling REST api, body in the response if flushed out after I read it from the response for the first time. I had a Sysout statement in service implementation class where I was reading the body content.
Recommendation: Read the body content only once and store it in a variable. Use it wherever required.

Feign get request with body

For some reason I need to call a GET method API and pass json request body for it. I really couldn't find an example for it. I wonder if it is even supported using feign.
How can I do that using feign?
Yes, Feign supports it. You can do the same as with POST requests:
#FeignClient(name = "clientName", url = "http://localhost:8888")
public interface SampleFeignClient {
#GetMapping("/remote")
String test(#RequestBody SampleRequestBody sampleRequestBody);
}
But be aware: a lot of servers ignore body or even refuse that kind of "non-standard" requests completely (GET or HEAD with request bodies).
According to the documentation the correct way to do it would be to use the #SpringQueryMap annotation.
#FeignClient(name = "clientName", url = "http://localhost:8888")
public interface SampleFeignClient {
#GetMapping("/remote")
String test(#SpringQueryMap SampleRequestBody sampleRequestBody);
}
You can find more information here

Spring #JsonView how can use request parameter or header

#JsonView
how can use like parameter from request:
#JsonView(header="range")
when response value,read request header range to exclude/include some field
JsonView provides "static" view mapping. so for your dynamic behaviour you can do like this:
// actual request handling is happened here
private ResponseEntity<SomeObject> processRequest();
// request handling with view limit in result
#JsonView(YourDefinedView.class)
#RequestMapping(value = "/request", headers={"range=include"})
public ResponseEntity<SomeObject> processWithView() {
return processRequest();
}
// request handling without view (no headers specified)
#RequestMapping(value = "/request")
public ResponseEntity<SomeObject> processWithoutView() {
return processRequest();
}
this will map your client to same request url, but depending on header it will provide view or not. Than you can create a set of methods, that will be using different #JsonView depending on headers information.
But with this you will limit only the data transfered to client, and the whole data load will happen on server. For example with database and JPA, if you would like not to fetch from database all that data you will end with javax.persistence.NamedEntityGraphs, which will change the general logic of your application - and will at the end of the day produce 2 different methods.
And if you would like to expose custom header with list of fields, to be serialized - custom DTO object, or Map<String, Object> (ugly-ugly-ugly) or custom HandlerMethodReturnValueHandler comes to your help.

Spring MVC detect ajax request

How to detect an ajax request in the best possible way?
I'm currently using this in my controller:
private boolean isAjax(HttpServletRequest request){
String header = request.getHeader("x-requested-with");
if(header != null && header.equals("XMLHttpRequest"))
return true;
else
return false;
}
But I don't like this way, I think there should have a better solution with Spring.
That is the only "generic" way to detect an Ajax request.
But keep in mind: that's not failproof, it is just a best effort attempt, it is possible to make an Ajax request without sending the X-Requested-With headers.
jQuery usually includes that header. Maybe another lib doesn't. The protocol certainly doesn't consider that header mandatory.
Just a note: Your code is perfectly valid, though you could write it a bit simpler:
private boolean isAjax(HttpServletRequest request) {
String requestedWithHeader = request.getHeader("X-Requested-With");
return "XMLHttpRequest".equals(requestedWithHeader);
}
There is a simple bullet proof solution. Simply send query parameter like ajax=1 from your ajax request and send a different value or do not send this parameter for regular request and check in your controller and take action accordingly.

Resources