Attempted read from closed stream - java

I'm attempted to make a request to the ROBLOX API to rank a user, however after about 15 minutes or so I get the error "attempted to read from closed stream. After researching this error, I close the client after each request, and release the connection from the request. However I still get the error. Any help would be greatly appreciated.
public void rankUser(String username, long rank, SlashCommandEvent exceptionCatcher) throws IOException {
try {
URL url = new URL(apiUrl + "v1/groups/" + group + "/users/" + getUserIdFromUsername(username, exceptionCatcher));
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPatch request = new HttpPatch(url.toString());
try {
request.addHeader("Cookie", ".ROBLOSECURITY=" + token);
request.addHeader("X-CSRF-Token", xcsrfToken);
request.addHeader("Content-Type", "application/json");
StringEntity params = new StringEntity("{\"roleId\":" + rank + "}");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
if(response.getHeaders("x-csrf-token") != null && xcsrfToken.equalsIgnoreCase("")) {
xcsrfToken = response.getHeaders("x-csrf-token")[0].getValue();
rankUser(username, rank, exceptionCatcher);
return;
}
request.releaseConnection();
statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
String responseAsString = getResponseAsString(response);
JsonParser parser = new JsonParser();
JsonObject jsonObject = (JsonObject) parser.parse(responseAsString);
} else if(statusCode == 429) {
exceptionCatcher.reply("You are being rate limited. Please try again in a few minutes.").setEphemeral(true).queue();
return;
} else {
System.out.println(getResponseAsString(response));
exceptionCatcher.reply("Could not rank user. Response: " + getResponseAsString(response)).setEphemeral(true).queue();
return;
}
httpClient.close();
} catch (Exception e) {
exceptionCatcher.reply("Could not rank. Ensure that the user is in the group. Error: " + e.getMessage()).setEphemeral(true).queue();
httpClient.close();
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}

Related

Mocking httpclient v4 in java Mockito

I hava a java apache client written as :
public JSONObject createProject(String accessToken) throws PostEditException {
JSONObject jobj = new JSONObject();
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost("https://"+HOST_TRANSPORT+"/api/projects/create");
try{
post.addHeader("Content-Type","application/json");
post.addHeader("Accept","application/json");
String authorizationValue = "Bearer "+accessToken;
post.addHeader("Authorization",authorizationValue);
HttpResponse response = client.execute(post);
if (response == null) {
System.out.println("this is null");
}
int code = response.getStatusLine().getStatusCode();
if (code != 200) {
HttpEntity entity = response.getEntity();
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
if (charset == null) {
charset = Charset.forName("UTF-8");
}
String errorBody = EntityUtils.toString(entity, charset);
log.info("createProject: Unable to process request. HTTP code: " + code + " responseBody: " + errorBody);
throw new PostEditException("createProject: Unable to process createProject request. HTTP code: " + code + " responseBody: " + errorBody);
} else {
HttpEntity entity = response.getEntity();
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
if (charset == null) {
charset = Charset.forName("UTF-8");
}
String taggedResult = EntityUtils.toString(entity, charset);
jobj = new JSONObject(taggedResult) ;
}
}catch (NoRouteToHostException re) {
log.error("createProject: unable to route to host."+re);
throw new PostEditException("createProject: unable to route to host.",re);
}catch (IOException ie) {
log.error("createProject: problem executing HTTP request."+ ie);
throw new PostEditException("createProject: problem executing HTTP request.",ie);
}catch (Exception e) {
log.error("createProject: an error occurred." +e );
throw new PostEditException("createProject: an error occurred",e);
} finally {
post.releaseConnection();
}
return jobj;
} //createProject
so , I am trying to write a test case to mock the HttpClient.
so I Wrote the Mockito test case as :
PowerMockito.mockStatic(HttpClientBuilder.class);
HttpClientBuilder builderMock = Mockito.mock(HttpClientBuilder.class);
PowerMockito.doReturn(builderMock).when(HttpClientBuilder.class, "create");
HttpClient clientMock = Mockito.mock(CloseableHttpClient.class);
CloseableHttpResponse responseMock = Mockito.mock(CloseableHttpResponse.class);
Mockito.doReturn(clientMock).when(builderMock).build();
Mockito.doReturn(responseMock).when(clientMock).execute(Mockito.any());
classname obj= new classname();
Method m = classname.class.getDeclaredMethod("createProject", String.class);
JSONObject result =(JSONObject) m.invoke(obj,"accesstoken");
But when I debug the program, I see the real httpclient is created instead of the mocked one. How Do I create the mock httpclient so that I can mock the status and response as well.

How can i create user in salesforce through REST api? Give me some examples

Am trying to create user into my salesforce account through REST api using java.But its returning 400 status code.Can you please guide me?
Here is the code am trying:
public static void createUsers() {
System.out.println("\n_______________ USER INSERT _______________");
String uri = baseUri + "/sobjects/User/";
System.out.println(uri);
try {
//create the JSON object containing the new lead details.
JSONObject lead = new JSONObject();
lead.put("FirstName", "Jake");
lead.put("LastName", "sully");
lead.put("Alias", "Jake");
lead.put("Email", "Jake#gmail.com");
lead.put("Username", "Jake#gmail.com");
lead.put("Name", "jake");
lead.put("UserRoleId","00E28000000oD8EEAU");
lead.put("Id", "10028000000GLSIAA4");
lead.put("EmailEncodingKey", "ISO-8859-1");
lead.put("TimeZoneSidKey", "Asia/Kolkata");
lead.put("LocaleSidKey", "en_US");
lead.put("ProfileId", "00e280000027hnGAAQ");
lead.put("LanguageLocaleKey", "en_US");
//Construct the objects needed for the request
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(uri);
httpPost.addHeader(oauthHeader);
httpPost.addHeader(prettyPrintHeader);
// The message we are going to post
StringEntity body = new StringEntity(lead.toString(1));
body.setContentType("application/json");
httpPost.setEntity(body);
//Make the request
HttpResponse response = httpClient.execute(httpPost);
//Process the results
System.out.println(response.toString());
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 201) {
String response_string = EntityUtils.toString(response.getEntity());
JSONObject json = new JSONObject(response_string);
// Store the retrieved lead id to use when we update the lead.
leadId = json.getString("id");
} else {
System.out.println("Insertion unsuccessful. Status code returned is " + statusCode);
}
} catch (JSONException e) {
System.out.println("Issue creating JSON or processing results");
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (NullPointerException npe) {
npe.printStackTrace();
}
}

How do I read HttpEntity without consuming it?

I've got org.apache.http.HttpResponse object, which I'm using at different places in the code. One of those places is for logging.
The problem is that when I run following log code:
HttpEntity entity = response.getEntity();
try {
String content = Base64.encodeToString(
EntityUtils.toByteArray(entity), Base64.DEFAULT);
sb.append(content + "\r\n");
} catch (Exception e) {
sb.append("\r\n\r\n====EXCEPTION=====\r\n" + e.toString()
+ "\r\n");
}
and than I try to read entry content in the actual processing code, that causes the code to throw following exception:
java.lang.IllegalStateException: Content has been consumed
My question is: how do I read the entity without consuming it in the log code?
UPDATE
here's the full code of the function I use to transform httpresponse to string:
static String toString(org.apache.http.HttpResponse response) {
try {
if (response == null) {
return "null";
}
StringBuilder sb = new StringBuilder();
sb.append("==============BEGIN HttpResponse================\r\n");
StatusLine sl = response.getStatusLine();
if (sl == null) {
sb.append("status line is null\r\n");
} else {
sb.append(String.format("%s %s\r\n", sl.getStatusCode(),
sl.getReasonPhrase()));
}
for (Header h : response.getAllHeaders()) {
if (h == null) {
sb.append("header is null\r\n");
continue;
}
sb.append(String.format("%s: %s\r\n", h.getName(), h.getValue()));
}
sb.append("\r\r\r\n");
HttpEntity entity = response.getEntity();
if (entity == null) {
sb.append("content is null");
} else {
try {
String content = Base64.encodeToString(
EntityUtils.toByteArray(entity), Base64.DEFAULT);
sb.append(content + "\r\n");
} catch (Exception e) {
sb.append("\r\n\r\n====EXCEPTION=====\r\n" + e.toString()
+ "\r\n");
}
}
sb.append("\r\n==============END HttpResponse================\r\n");
return sb.toString();
} catch (Exception e) {
return e.toString();
}
}
Ok. So what I ended up doing is implementing my own HttpEntity class, and than just using response.setEntity(...) to replace the previous entity. That class stores the result as binary array and returns it as many times as necessary.
It might give you some performance issues, but will work:
Example of my HttpClient with logging.
private CloseableHttpResponse invoke(HttpRequestBase http) {
try {
CloseableHttpResponse response = client.execute(http);
if (http instanceof HttpPost) {
InputStream inputStream = ((HttpPost) http).getEntity().getContent();
String body = IOUtils.toString(inputStream, Charset.defaultCharset());
HttpEntity respBody = response.getEntity();
String responseBody = StreamUtils.copyToString(respBody.getContent(), Charset.defaultCharset());
response.setEntity(new StringEntity(responseBody));
LOG.info(String.format("Sending request: [%s] %s => [%s] \nPayload:\n%s \nResponse:\n%s", http.getMethod(), http.getURI(), response.getStatusLine(), body, responseBody));
} else {
LOG.info(String.format("Sending request: [%s] %s => [%s]", http.getMethod(), http.getURI(), response.getStatusLine()));
}
return response;
} catch (IOException e) {
throw new RuntimeException("HTTP request failed: " + http.toString(), e);
}
}
Main idea is following:
1. make http call
2. copy to string your response body:
HttpEntity respBody = response.getEntity();
String responseBody = StreamUtils.copyToString(respBody.getContent(), Charset.defaultCharset());
log it
set new response entity like response.setEntity(new StringEntity(responseBody));
This example work good for small test framework, not sure it's good code for production application

how to obtain a JSESSIONID cookie

I have an android client and this is how I am doing a request to my tomcat server:
protected String executeRequest(String url)
{
BasicHttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
String output = "", line = "";
try
{
HttpGet getRequest = null;
DefaultHttpClient httpClient = new DefaultHttpClient();
try
{
getRequest = new HttpGet(url);
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
getRequest.addHeader("accept", "application/json");
HttpResponse response = httpClient.execute(getRequest);
if (response.getStatusLine().getStatusCode() != 200)
{
response.getStatusLine().getStatusCode();
return null;
}
BufferedReader br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
while ((line = br.readLine()) != null)
{
output += line;
}
httpClient.getConnectionManager().shutdown();
}
catch (ClientProtocolException e)
{
e.printStackTrace();
Log.w(TAG, e.getMessage());
}
catch (IllegalStateException e)
{
e.printStackTrace();
Log.w(TAG, e.getMessage());
}
catch (IOException e)
{
e.printStackTrace();
Log.w(TAG, e.getMessage());
}
if(output.equals(""))
{
output = null;
}
return output;
}
Now I want to be able to get the JSESSIONID cookie. I understand that I need to provide with a cookie like explained here, but how do I get the jSessionId in the first time?
Thanks!
Ok, here is how I did it. Don't know if there is any easier way:
HttpResponse response = httpClient.execute(getRequest);
Header[] headers = response.getHeaders("Set-Cookie");
for(int i = 0; i < headers.length; i++)
{
if(headers[i].getName().equals("Set-Cookie"))
{
String pattern1 = "JSESSIONID=";
String pattern2 = ";";
Pattern p = Pattern.compile(Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2));
Matcher m = p.matcher(headers[i].getValue());
if(m.find())
{
sessionId = m.group(1);
break;
}
}
}

Android web view not sending post array to php?

the problem is that i don't receive any $_POST['registerationID'] from android webview
i have this code in android java ::
#Override
protected void onRegistered(Context context, String registrationId) {
String URL_STRING = "http://mysite.org/mysite/index.php/user/notification/";
Log.i(MyTAG, "onRegistered: registrationId=" + registrationId);
// notification
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("registrationId",registrationId));
try{
HttpPost httppost = new HttpPost(URL_STRING);
httppost.setHeader("Content-Type","text/plain");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setBooleanParameter("http.protocol.expect-continue", false);
HttpResponse response = httpclient.execute(httppost);
Log.i("LinkPOST:", httppost.toString());
Log.i("postData", response.getStatusLine().toString());
HttpEntity httpEntity = response.getEntity();
if (httpEntity != null){
//System.out.println("Not Empty");
String responseBody = EntityUtils.toString(httpEntity);
System.out.println(responseBody);
} else {
System.out.println("Empty");
}
}
catch(Exception e)
{
Log.e("log_tag", "Error in http connection "+e.toString());
}
}
and i handle the httprequest post in php (using codeigniter) as the following :
function notification() {
$registrationId = $_POST['registrationId'];
if($this->session->userdata('emailid')) {
//echo 'working from inside the if statement'.$this->session->userdata('emailid');
//$query = $this->db->query('INSERT INTO user (`deviceid`) VALUES ('.$_GET['registerationID'].') where `emailid`='.$this->session->userdata('emailid').';');
$data = array(
'deviceid' => $registrationId,
);
$this->db->where('emailid', $this->session->userdata('emailid'));
$this->db->update('user', $data);
if($this->db->affected_rows() == 1) {
// some code
}
else {
// some code
}
}
Try with the function bellow. It works for me.
Just Fill a HashMap for your post params
private static void post(String url, Map<String, String> params)
throws IOException {
URL url;
try {
url = new URL(endpoint);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("invalid url: " + endpoint);
}
StringBuilder bodyBuilder = new StringBuilder();
Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
// constructs the POST body using the parameters
while (iterator.hasNext()) {
Entry<String, String> param = iterator.next();
bodyBuilder.append(param.getKey()).append('=')
.append(param.getValue());
if (iterator.hasNext()) {
bodyBuilder.append('&');
}
}
String body = bodyBuilder.toString();
Log.v(TAG, "Posting '" + body + "' to " + url);
byte[] bytes = body.getBytes();
HttpURLConnection conn = null;
try {
Log.e("URL", "> " + url);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
// post the request
OutputStream out = conn.getOutputStream();
out.write(bytes);
out.close();
// handle the response
int status = conn.getResponseCode();
if (status != 200) {
throw new IOException("Post failed with error code " + status);
}
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
Try replacing
httppost.setHeader("Content-Type","text/plain")
by
httppost.setHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8")
which is expected by your php code.
For more detail please see this SO question

Categories