apache httpclient- most efficient way to read response - apache-httpclient-4.x

I'm using apache httpcompnonents library for httpclient. I want to use it in a multithreaded application where number of threads are going to be really high and there would be frequent http calls. This is the code I'm using to read the response after execute call.
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity);
I just want to confirm that is it the most efficient way of reading the response?
Thanks,
Hemant

This in fact represents the most inefficient way of processing an HTTP response.
You most likely want to digest the content of the response into a domain object of a sort. So, what is the point of buffering it in-memory in a form of a string?
The recommended way to deal with response processing is by using a custom ResponseHandler that can process the content by streaming it directly from the underlying connection. The added benefit of using a ResponseHandler is that it completely relieves from dealing with connection release and resource deallocation.
EDIT: modified the sample code to use JSON
Here's an example of it using HttpClient 4.2 and Jackson JSON processor. Stuff is assumed to be your domain object with JSON bindings.
ResponseHandler<Stuff> rh = new ResponseHandler<Stuff>() {
#Override
public Stuff handleResponse(
final HttpResponse response) throws IOException {
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(
statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
HttpEntity entity = response.getEntity();
if (entity == null) {
throw new ClientProtocolException("Response contains no content");
}
JsonFactory jsonf = new JsonFactory();
InputStream instream = entity.getContent();
// try - finally is not strictly necessary here
// but is a good practice
try {
JsonParser jsonParser = jsonf.createParser(instream);
// Use the parser to deserialize the object from the content stream
return stuff;
} finally {
instream.close();
}
}
};
DefaultHttpClient client = new DefaultHttpClient();
Stuff mystuff = client.execute(new HttpGet("http://somehost/stuff"), rh);

Related

Illegal assignment from System.JSONParser to JsonParser

In JsnoToApex class I try to GET JSON file from https://openweathermap.org/current. When I try to parse JSON.CreateParses I get these error: Illegal assignment from System.JSONParser to JsonParser
I try to make API that show weather in London.
public with sharing class JsonToApex {
#future(callout=true)
public static void parseJSONResponse() {
String resp;
Http httpProtocol = new Http();
// Create HTTP request to send.
HttpRequest request = new HttpRequest();
// Set the endpoint URL.
String endpoint = 'https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22';
request.setEndPoint(endpoint);
// Set the HTTP verb to GET.
request.setMethod('GET');
// Send the HTTP request and get the response.
// The response is in JSON format.
HttpResponse response = httpProtocol.send(request);
resp = response.getBody();
JSONParser parser = JSON.createParser(resp);
JsonMapper response = (JsonMapper) System.JSON.deserialize(res.getBody(), JsonMapper.class);
}
}
I expect to get Json file and in future map it using https://json2apex.herokuapp.com/
The problem was in first JSONParser. I had to add System.JSONParser to make it work.
System.JSONParser parser = JSON.createParser(resp);
You may have two approaches:
If you have already map the JSON into an Apex class, you may just use
JSON2Apex aClass = (JSON2Apex) System.JSON.deserialize(resp, JSON2Apex.class);
Where JSON2Apex is the mapping Apex class.
Use the JSON.deserializeUntyped(String jsonString) to deserialize the JSON to any Object in Apex class, like:
Map<String, Object> objMap = (Map<String, Object>) JSON.deserializeUntyped(resp);

Get JSON response from Jenkins API in java which requires sign in

I want to read JSON response coming from jenkins API to read last build details. I am using http://jenkins_server/job/job_name/lastBuild/api/json. When I type this URL in browser, I need to sign in to my Jenkins job and after that I get proper json response.
I have written a java code to read JSON response from same Jenkins API. But I get "Server returned HTTP response code: 403" as I have not handled the authentication part in code.
public class GetJSONResponse {
public static void main(String[] args) throws MalformedURLException, IOException, JSONException {
InputStream is = new URL("http://jenkins_server/job/job_name/lastBuild/api/json").openStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
JSONObject json = new JSONObject(sb.toString());
System.out.println(json.toString());
}
}
I searched alot on how to get JSON response from jenkins API which reqiures authentication , but didn't find anything useful. How do I add authentication part in my code? Can anybody please help me with this?
Thanks in advance.
I resolved my problem after changing the jenkins config.xml "useSecurity" fileld.
Change <useSecurity>true</useSecurity> to <useSecurity>false</useSecurity>
And I got correct JSON response.

How to send serializable request object with httpClient in .net core?

I'm new in .net and I'm looking for a way (if exists) to be able to pass a request object to a http client without "manually" serialize it to json. I did some java implementations in the past and there it was done under the hood and I thought that it should be possible also in .netCore
This is the request object:
public class Request
{
[JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)]
public int Number { get; set; }
}
and I'm looking for something like:
var request = new Request {Number=2};
client.PostAsync("url", request)
I found a similar implementation, but that does not seems to be .netcore compatible:
https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Client/5.2.4-preview1
Is there anything similar for .netcore?
Thanks
You will still need to serialize the object to a JSON string.
The referenced Microsoft.AspNet.WebApi.Client library in question would have the PostAsJsonAsync extension method along with many others for extending HttpClient.
Which internally may have looked like this.
public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string requestUri, T obj) {
var json = JsonConvert.SerializeObject(obj);
var content = new StringContent(json, Encoding.UTF8, "application/json");
return client.PostAsync(requestUri, content);
}
and used like
using System.Net.Http;
//...
var request = new Request { Number = 2 };
var response = await client.PostAsJsonAsync("url", request);

Get the real response time using Apache Httpclient

I'm trying to determine the proper way to measure the full time taken to obtain the full response from the HTTP request. From the time the HTTP GET is sent, to the time the client gets the very last entity byte from the server.
What would be the best way to do this?
For instance, in this modified version of code borrowed from the httpclient tutorial. Would the following give me the time it took to get the entire MP4 from the server?
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://server_ip/video.mp4");
//Start the timer here
long start_time = System.currentTimeMillis();
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
try {
final byte[] lBytes = new byte[4096];
do{
//Consume 4KB from the entity inputStream
instream.read(lBytes);
} while(instream.read(lBytes) != -1)
//Stop the timer here
long stop_time = System.currentTimeMillis();
//Get total download time?
long mp4DownloadTime = stop_time - start_time;
}
finally {
instream.close();
}
}
}
finally {
response.close();
}
Does that make any sense? I don't quite understand how the HttpClient deals with the entity content. When running a tcpdump on the interface, I see that I get the full entity regardless of what I consume in the Java code... Any guidance would be appreciated.

How does play.libs.Json.fromJson handled a List<T> in Java?

I'd like to use the Json library that comes with the play 2.1 framework.
But I'm stuck with deserializing a json object back into a java List.
With gson, you can write s.th. like
Type type = new TypeToken<List<XYZ>>(){}.getType();
List<XYZ> xyzList = gson.fromJson(jsonXyz, type);
Is there a way to do the same with play.libs.Json.fromJson ?
Any help appreciated.
Edit (17.12.2013):
I did the following to work around the problem. I guess there is a better way, but I didn't found it.
List<MyObject> response = new ArrayList<MyObject>();
Promise<WS.Response> result = WS.url(Configuration.getRestPrefix() + "myObjects").get();
WS.Response res = result.get();
JsonNode json = res.asJson();
if (json != null) {
for (JsonNode jsonNode : json) {
if (jsonNode.isArray()) {
for (JsonNode jsonNodeInner : jsonNode) {
MyObject mobj = Json.fromJson(jsonNodeInner, MyObject.class);
response.add(bst);
}
} else {
MyObject mobj = Json.fromJson(jsonNode, MyObject.class);
response.add(bst);
}
}
}
return response;
The Json library for Play Java is really just a thin wrapper over the Jackson JSON library (http://jackson.codehaus.org/). The Jackson way to deserialize a list of custom objects is mentioned here.
For your case, once you parse the json from the response body, you would do something like this, assuming MyObject is a plain POJO:
JsonNode json = res.asJson();
try{
List<MyObject> objects = new ObjectMapper().readValue(json, new TypeReference<List<MyObject>>(){});
}catch(Exception e){
//handle exception
}
I'm assuming you were asking about Play Java based on your edit, Play Scala's JSON library is also based on Jackson but has more features and syntactic sugar to accommodate functional programming patterns.
You can use the following code:
List<YourClass> returnedRoles = new ObjectMapper().readValue(jsonString
,TypeFactory.defaultInstance().constructCollectionType(List.class,
YourClass.class));