Obtain object and header simultaneously with spring - java

I am requesting a object to a external api service using getForObject() of the class RestTemplate and I will like to change the url for the service to also sent me a header with relevant information, I have been reading and found headForHeaders() with will return the header but will force me to make 2 calls to the service.
There is any way to be able to retrive the header data and the object in the same call?

getForObject() does not support setting headers. You can use the exchange() method and pass headers. And then use getBody() method. You can also use getForEntity() which providesgetHeaders() and getBody().

I have implemented it using getForEntity() as already mentioned, I leave my particular solution in case is useful for someone.
HttpEntity<Object> responseEntity = new RestTemplate().getForEntity(url, Object.class);
HttpHeaders header = responseEntity.getHeaders();
String headInformation = header.getFirst("headerValue");
Object newObject = responseEntity.getBody();

Related

Use spring reactive webclient to pass protobuff request

I am using spring framework reactive webclient to make a call like below
webClient.post()
.uri("/v/score/$model")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(gson.toJson(request))
.accept(MediaType.APPLICATION_JSON)
.header("Client-Id", clientId)
.awaitExchange()
.awaitBody<ScoringResponse>()
which is working fine. Now I wan to pass the request as a protobuff object instead of json. How can I do that ?
Set the media type to application/octet-stream and pass your proto model in a byte array form by using the .toByteArray() method. On the receiving end you can use the static method {proto generated class}.parseFrom({your bytes come here}) to rebuild the proto object.
Do not forget the POST method request is basically a body content ;)

Collision between RestTemplate with basic authentication and exchange method

I am using Spring 4.3 and SpringBoot 1.5 to create a component that has to call an external REST service. This external service requests HTTP Basic Authentication.
I found that SpringBoot provides a very useful builder to set up RestTemplate properties, such as basic authentication, RestTemplateBuilder.
To call the external REST service I have to use the method RestTemplate.exchange, because of the List<T> return type.
new RestTemplateBuilder().basicAuthorization(username, password)
.build()
.exchange("/some/path/with/variables",
HttpMethod.GET,
new HttpEntity<>(new HttpHeaders()),
new ParameterizedTypeReference<List<Integer>>() {},
some, params)
The problem here is that the signature of the exchange method requests an object of type HttpEntity, that is basically a container of HttpHeaders.
The question is, will the HttpEntity object, passed as input parameter to the exchange method, subscribe the Basic Auth header set using the RestTemplateBuilder.basicAuthorization method?
Thanks a lot.
I have done some experiments during the past couple of days. The instance of HttpEntity passed to the exchange method does not subscribe the information relative to the Basic Authentication set by the RestTemplateBuilder. The two sets of headers are merged into one.
Nice shot, Spring ;)

Access HTTP response when using Jersey client proxy

I'm using Jersey 2.22 to consume a REST api.
The approach is contract-first, a service interface and wrappers are used to call the REST api (using org.glassfish.jersey.client.proxy package).
WebClient webClient = ClientBuilder.newClient();
WebTarget webTarget = webClient.getWebTarget(endPoint);
ServiceClass proxy = WebResourceFactory.newResource(ServiceClass.class, webTarget);
Object returnedObject = proxy.serviceMethod("id1");
The question is: how to get the underlying HTTP response (HTTP status + body)?
When the returnedObject is null, I need to analyze the response to get error message returned for example.
Is there a way to do it?
I saw that we can plug filters and interceptors to catch the response, but that's not exactly what I need.
You should return Response as the result of the interface method instead of the plain DTO.
I'm not sure about the level of control you're expecting (considering your reply to #peeskillet comment), but the Response object will give you the opportunity to fine tune your server's response (headers, cookies, status etc.) and read all of them at the client side - as you might see taking a look at Response's members like getStatus() and getHeaders().
The only gotcha here is how to get the body. For this, I'd tell you to use readEntity(Class<T>) (not the getEntity() method as one might try at first). As long as you have the right media type provider registered, you can extract the entity as your DTO class in a easy way.
For example, if you are using maven, jersey and JSON as media type, you can add the following dependency (and take the provider's registration for granted):
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
Then, get the entity body deserialized using:
Response resp = proxy.serviceMethod("id1");
int status = resp.getStatus();
String statusText = resp.getStatusInfo();
String someHeader = resp.getHeaderString("SOME-HEADER");
YourCustomDTO obj = resp.readEntity(YourCustomDTO.class);
When querying a list of your custom objects (i.e. method returns a JSON array) use the array type to read the body.
Response resp = proxy.serviceMethodThatReturnsCollection();
YourCustomDTO[] obj = resp.readEntity(YourCustomDTO[].class);
Please notice that after reading the body, the stream is closed and trying getEntity() may throw an exception.
Hope it helps.

Is there a standard way in Spring to pass a body with a DELETE request to a REST endpoint?

I am implementing a Spring client for an existing REST API and I need to invoke a DELETE while, at the same time, passing an access token in the request body, like this:
{
"access_token": "..."
}
The problem is that, using the method that works for POST, the transmitted body is empty (I have intercepted the request body and made sure) and I cannot be authorised without this access token. This is what I am doing:
RestTemplate restTemplate = new RestTemplate();
UserRequest ur = new UserRequest(access_token);
HttpEntity<UserRequest> entity = new HttpEntity<>(ur);
restTemplate.delete(url, entity);
I have no control over the API itself, so I don't have the option of passing the token as url parameter.
Is there a way to do this in Spring, or do I have to build my own HttpUrlConnection like described for instance in this SO answer?
In the RestTemplate object in Spring there's an exchange method.
The parameters are :
the url
the method, in your case HttpMethod.DELETE
the entity (with the body you have to transmit)
the response type
some object you could pass
Hope this help

Logging Rest Assured's own headers

I'm trying to get access to the HTTP headers that are injected by Rest Assured. Spring's Mock MVC gives you access to pretty much everything via the MvcResult, and you can use this result to log pretty much anything you would like about the request and response. The only way I can see how to do this is in RestAssured is with a Filter. However, it gives you limited access to the request (you just get the RequestSpecification). I understand that it might be tricky to get access to headers that are added by the HttpClient, but it doesn't look like you can even get access to headers that are added by Rest Assured itself. For example, I can't see any OAuth related headers, nor content-type or content-length. The only headers that appear are those that were manually added using, for example, .contentType(ContentType.XML)
Is there any other way to get access to those headers? I don't need to modify the request, I just want to be able to log all of it and the headers that are injected by Rest Assured.
I found that it's possible to register your own HttpClientFactory with RestAssured:
RestAssured.config().httpClient(
HttpClientConfig.httpClientConfig().httpClientFactory(
new CustomHttpClientFactory())
So I created a new factory that returns an HTTP client into which I inject some request and response interceptors.
public class CustomHttpClientFactory extends HttpClientConfig.HttpClientFactory {
#Override
public HttpClient createHttpClient() {
DefaultHttpClient client = new DefaultHttpClient();
client.addRequestInterceptor((request, ctx) -> {
// do what you will
});
client.addResponseInterceptor((response, ctx) -> {
// do what you will
});
return client;
}
}
This gives you almost full access to manipulate the request and response. One thing to remember is that if you're going to read from the response's entity, you should first wrap it in a BufferedHttpEntity to make it re-readable:
if (response.getEntity() != null && !response.getEntity().isRepeatable()) {
response.setEntity(new BufferedHttpEntity(response.getEntity()));
}
Another problem I ran into is when trying to see the OAuth related information. When using RestAssured's OAuth functionality, it adds its own OAuthSigner interceptor to the HTTP client right before executing the request. This means that it will always be the last interceptor to be called and any interceptor you may have already injected will be called before the request ever gets signed. Because I don't really need to see the signature for now, I didn't investigate this further and I'm leaving it as an exercise for the reader. ;)

Categories