I'm using jersey http client to send requests to some remote API. I need to measure how much time does it take to send request to the server and wait until it gets processed and server returns me some status code. Is there a way how I can do it with jersey?
Here is my code of post method:
public Response post(String targetUrl, Entity entity)
{
return client.target(targetUrl)
.request()
.accept(MediaType.APPLICATION_JSON_TYPE)
.header(SERVER_AUTH, true)
.post(entity);
}
Actually, it was my fault. By default, this client is synchronized so it blocks thread until response is received. But my problem was that URL was incorrect and code immediately returned status 'Resouce not found.'
Related
From the docs,
immediately after sending the 101
(Switching Protocols) response, the server is expected to continue
responding to the original request as if it had received its
equivalent within the new protocol (i.e., the server still has an
outstanding request to satisfy after the protocol has been changed,
and is expected to do so without requiring the request to be
repeated).
If the Upgrade header field is received in a GET request
and the server decides to switch protocols, it first responds with a
101 (Switching Protocols) message in HTTP/1.1 and then immediately
follows that with the new protocol's equivalent of a response to a
GET on the target resource. This allows a connection to be upgraded
to protocols with the same semantics as HTTP without the latency cost
of an additional round trip.
I have made my interceptors(Using OkHttp) as follows
public class H2cUpgradeRequestInterceptor implements Interceptor {
private static final Log logger = LogFactory.getLog(H2cUpgradeRequestInterceptor.class);
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request upgradeRequest = request.newBuilder().addHeader("Connection", "Upgrade, HTTP2-Settings")
.addHeader("Upgrade", "h2c").addHeader("HTTP2-Settings", "AAMAAABkAARAAAAAAAIAAAAA").build();
Response upgradeResponse = chain.proceed(upgradeRequest);
if (upgradeResponse != null && upgradeResponse.code() == HttpStatus.SC_SWITCHING_PROTOCOLS) {
logger.debug("Switching Protocols success"); // Success. Got 101 in reply.
}
upgradeResponse.body(); // returns null
// I am clueless on how to read the response hereafter.
// As per the docs, the 101 status code reply will be followed by a data stream. How can I access this?
return upgradeResponse;
}
}
So basically, for a single request. I will receive 101 as response first if the upgrade is successful, then followed by another response as per the upgraded protocol(if my understanding is right?). Is there anyway to achieve this with OkHttp? Or, Any other client also would be helpful.
Thanks!
I'm new to Java and found a confusing behaviour related with RestTemplate.
It happened with an API returning large body (~5MB) over a quite slow network condition. The code is like below
ResponseEntity<MyEntity[]> result = restTemplate.exchange(url, HttpMethod.GET, entity, MyEntity[].class);
And also a ClientHttpRequestInterceptor is set to log before and after the request.
The confusing thing is that the after request log is logged only a while after remote server giving the response, and the HTTP Status code can be print in the log.
But the above statement took much more time to finally receive the data. Look inside the thread stack, it was reading data from socket.
I also look inside the resttemplate class and found:
response = request.execute();
handleResponse(url, method, response);
if (responseExtractor != null) {
return responseExtractor.extractData(response);
}
It seems to extractData after the execute().
My doubt is:
How does the client side know the status code even before get all the data? It just extracts necessary fields from the top packets?
Since the server has already sent out the response, where the response data is stored during the process?
It stores the data that it receives from the underlying HTTP in memory.
Client side can know what's the status code because with HTTP you get the headers and status code first before the response body. But this doesn't matter with RestTemplate as it promises to give you an object of ResponseEntity in the end, which contains everything from the http response be it status codex headers or body.
RestTemplate is an abstraction over an HttpClient, most client's give you the option to implement callbacks for separate events like onHeadersReceived(), onStatusReceived() etc. But if you are using RestTemplate this means you don't require such fine grained control.
I am currently sending more than one Emails at a time using Gmail API. I am doing this sequentially:
Send an Email via GmailAPI
Wait for response from GmailAPI.
When response is received, update the Record with ThreadID returned by GmailAPI.
Repeat steps 1-3 for other emails.
I was reading about batching your sendEmail API requests,so that we make one call to API and handle the responses.
Although i am able to batch my all request and send it,
I am not sure about how to handle Responses. If i have 30 Send Email Requests in the batch request, when the response is received for the batch, how do i figure out which response is for which Email?
Here is my Implementation
BatchRequest batch = gmailService.batch();
gmailService.users().messages().send("me", message).queue(batch, callback);
batch.execute();
final List<Message> messages = new ArrayList<Message>();
JsonBatchCallback<Message> callback = new JsonBatchCallback<Message>() {
public void onSuccess(Message message, HttpHeaders responseHeaders) {
System.out.println("MessageThreadID:"+ message.getThreadId());
System.out.println("MessageID:"+ message.getId());
synchronized (messages) {
messages.add(message);
}
}
#Override
public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders)
throws IOException {
}
};
I am not sure about how to handle Responses. If i have 30 Send Email Requests in the batch request, when the response is received for the batch, how do i figure out which response is for which Email?
According to this Batch Request Response document:
Response to a batch request
The server's response is a single standard HTTP response with a
multipart/mixed content type; each part is the response to one of the
requests in the batched request, in the same order as the requests.
Like the parts in the request, each response part contains a complete
HTTP response, including a status code, headers, and body. And like
the parts in the request, each response part is preceded by a
Content-Type header that marks the beginning of the part.
You could get the the complete HTTP response, its status code, its headers, and its body in the order to which you made the request. So response one is for 1st request, response 2 is for 2nd request and so forth. In this way, you might figure the response for which Email.
I have a question on how to fetch response body in Jersey client when server returns some sample text with status code 401. Sample service is setup as follows:
#GET
#Path("test401withcontent")
public Response get401TestWithContent()
{
return Response.status(401).entity("return some text").build();
}
On the client side (using Jersey 1.17) ClientResponse.getEntity prints null.
Noticed that content-length of headers has the right number (16 in this case.)
Is there a different way to get response when return code is 401?
Have deployed you method to my test web site and used below client got currect response.
Client client = ClientBuilder.newClient();
//System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
Response response = client.target(
"http://jerseyexample-ravikant.rhcloud.com/rest/jws/test401withcontent").
request().get(); System.out.println(response.readEntity(String.class));
I have a RESTful Java web service that I built using Jersey. The client for it defines a resource with the following method:
#Override
public String saveWidget(Widget widget) {
return webResource.path("user").type(MediaType.APPLICATION_JSON).entity(widget).post(String.class, Widget.class);
}
Then, a driver using this client:
public class Driver {
public static void main(String[] args) {
WidgetClient client;
WidgetClientBuilder builder = new WidgetClientBuilder();
client = builder.withUri("http://localhost:8080/myapi").build();
Widget w = getSomehow();
String widgetUri = client.getWidgetResource().saveWidget(w);
System.out.println("Widget was saved URI was returned: " + widgetUri);
}
}
When I run this I get:
Exception in thread "main" com.sun.jersey.api.client.UniformInterfaceException: POST http://localhost:8080/myapi/widget returned a response status of 400 Bad Request
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:688)
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:570)
at com.my.myapi.WidgetResource.saveWidget(WidgetResource.java:27)
at com.my.myapi.Driver.main(Driver.java:32)
I know the service endpoint is valid because I can hit it from another (non-Java) web client without issues. This means that either my Widget instance is malformed or that there is something with my Java client method (saveWidget). I ruled out my w Widget being bad by serializing it into JSON, and then copying it into my non-Java web client and POSTing to the same endpoint (no issues arose). So this tells me I have the client method configured wrong. Any ideas?
This is regarding making a call POST call using Jersey client.
For jersey client, default client configuration uses ChunkedEncoding and gzip. This can be checked in request headers for POST call. Content length of payload (JSON String or any object mapper pojo) and request headers received by post call i.e. header name CONTENT-LENGTH, CONTENT-ENCODING. If there is difference, POST call might return 400 bad request. (Something like unable to process JSON). To solve this, you can disable ChunkedEncoding, gzip encoding. Code snippet for the same:
clientConfiguration.setChunkedEncodingEnabled(false);
clientConfiguration.setGzipEnabled(false);
Client client = (new JerseyClientBuilder(environment)).using(clientConfiguration).using(environment).build("HTTP_CLIENT");
WebTarget webTarget = client.target(endpoint);
Response response = webTarget.path(path).request(MediaType.APPLICATION_JSON).post(Entity.json(jsonString));
.post(String.class, Widget.class);
You appear to be posting a Class object, not a Widget object.