Can not read request body from servlet - java

This is my controller code:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public #ResponseBody String testPost(#RequestParam(value = "testParam") int testParam, HttpServletRequest request) {
try {
System.out.println("body is "+BufferUtil.getHttpRequestBody(request));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
BufferUtil.getHttpRequestBody(request) is
public static String getHttpRequestBody(HttpServletRequest request)
throws IOException {
Scanner s = null;
try {
s = new Scanner(request.getInputStream(), "UTF-8")
.useDelimiter("\\A");
} catch (IOException e) {
e.printStackTrace();
}
return s.hasNext() ? s.next() : "";
}
This is the code to use to test controller:
HTTPUtil.sendRequest("http://localhost:8081/es09android/test?testParam=1", "POST", "hello world");
sendRequest() implementation:
public static HttpResponse sendRequest(String url, String method,
String data) {
DataOutputStream wr = null;
BufferedReader in = null;
HttpResponse httpResponse = new HttpResponse();
try {
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod(method);
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setDoOutput(true);
if (data != null) {
wr = new DataOutputStream(con.getOutputStream());
wr.write(data.getBytes(UTF8_CHARSET));
}
int responseCode = con.getResponseCode();
httpResponse.setResponseCode(responseCode);
if (httpResponse.isOk()) {
in = new BufferedReader(new InputStreamReader(
con.getInputStream(), "UTF8"));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
httpResponse.setData(response.toString());
}
return httpResponse;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (wr != null) {
try {
wr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
If I run it and then send request, controller will not print body. But if remove #RequestParam(value = "testParam") from the controller, everything will be ok. What is wrong?

Edited after more information provided in comments below
I assume what's hapening is that s.hasNext() is returning false, because you're at the end of the request's InputStream. This is as designed, you can only read the InputStream once.
This question has a good example of a way you can cache the request to read it more than once.
This question describes a way you can use Spring to log the entire request, which seems to be what your aim is in your question.

Related

Java HttpURLConnection invoke remote server and returned 500 status

I want to invoke remote server using HttpURLConnection, here is my function:
public String invokeAwvsServer(String api, String param, String method){
System.out.println(api+param);
BufferedReader reader = null;
HttpURLConnection connection = null;
OutputStreamWriter out = null;
try {
URL url = new URL(api);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod(method);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("X-Auth", apiKey);
connection.connect();
if(method.equalsIgnoreCase("POST")){
out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
out.append(param);
out.flush();
}
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
StringBuffer res = new StringBuffer();
while ((line = reader.readLine()) != null) {
res.append(line);
}
return res.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(connection != null){
connection.disconnect();
}
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "error";
}
I use this function in its own class and works well, but if I call it in other class ,the remote server return 500 status code and JVM throws exception like:
java.io.IOException: Server returned HTTP response code: 500 for URL:...
What`s the reason?Thanks a lot:)

Trouble with "inputstream" when creating mobile app that downloads weather information (with AsyncTask)

I'm trying to make a mobile app that downloads info from the openweathermap.org apis. For example, if you feed that app this link: http://api.openweathermap.org/data/2.5/weather?q=Boston,us&appid=fed33a8f8fd54814d7cbe8515a5c25d7 you will get the information about the weather in Boston, MA. My code seems to work up to the point where I have to convert the input stream to a string variable. When I do that, I get garbage. Is there a particular way to do this seemingly simple task in a proper way? Here is my code so far...
private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
// params comes from the execute() call: params[0] is the url.
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return null;
}
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
TextView test = (TextView) findViewById(R.id.test);
if(result!=null) test.setText(result);
else{
Log.i(DEBUG_TAG, "returned result is null");}
}
}
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.i(DEBUG_TAG, "The response is: " + response);
is = conn.getInputStream();
String text = getStringFromInputStream(is);
//JSONObject json = new JSONObject(text);
//try (Scanner scanner = new Scanner(is, StandardCharsets.UTF_8.name())) {
//text = scanner.useDelimiter("\\A").next();
//}
//Bitmap bitmap = BitmapFactory.decodeStream(is);
return text;
}catch(Exception e) {
Log.i(DEBUG_TAG, e.toString());
}finally {
if (is != null) {
is.close();
}
}
return null;
}
private static String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
Check this library . Is An asynchronous callback-based Http client for Android built on top of Apache’s HttpClient libraries.

How to test method with URL as parameter which produces a json using mockito

I am passing a service url which will fetch a json. I am mapping the json to response class using object mapper. How will i mock the url to invoke the actual service in test case?
public String QUOTE_SUMMARY_URL = "http://localhost:8181/omnesys_sb/quote";
#SuppressWarnings("deprecation")
public Quotesummary getQuoteSummary(final String urlString) throws JsonParseException, JsonMappingException, IOException {
String line, jsonString = null;
HttpURLConnection httpURLConnection = null;
ObjectMapper mapper = new ObjectMapper();
String urlStr = urlString != null ? urlString : QUOTE_SUMMARY_URL;
try {
URL url = new URL(urlStr);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Accept", "application/json");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line + '\n');
}
jsonString = stringBuilder.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpURLConnection.disconnect();
}
Quotesummary quoteSummary = mapper.readValue(jsonString, Quotesummary.class);
System.out.println(""+mapper.writerWithDefaultPrettyPrinter().writeValueAsString(quoteSummary));
return quoteSummary;
}

android - httpsurlconnection 'get' 405 - method not allowed

I am using a 'get' method on HttpsUrlConnection. When i am testing my code on eclipse (Windows) it works fine. When i compress it to a jar file and use it on android studio it gives me '405 - method not allowed'. What's mean, I am running the method with bad verb (expected GET).
This is how i set the http method type:
conn.setRequestMethod("GET");
I am setting the http method to 'get' and when i debug it - conn.getRequestMethod = GET and conn.delegate.getRequestMethod = POST.
The error response is - {"Message":"The requested resource does not support http method 'POST'."}
EDITED - code added:
public static HttpsURLConnection getClient(URL url, LoginToken securityToken, RequestMethod methodType, String requestFormat, String responseFormat) throws IOException, SecurityTokenException {
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.addRequestProperty("Accept-Charset", "UTF-8");
conn.addRequestProperty("Content-Type", requestFormat);
conn.addRequestProperty("Accept", responseFormat);
conn.addRequestProperty("User-Agent", "***SDK/1.0");
conn.setRequestProperty("Cache-Control", "no-cache");
if(securityToken != null) {
LoginToken.ValidateToken(securityToken);
conn.addRequestProperty("Authorization", String.format("Bearer %1$s", new Object[]{securityToken.getTemporarySecurityCode()}));
}
conn.setRequestMethod(methodType.toString());
conn.setUseCaches(false);
conn.setDoOutput(true);
return conn;
}
public Boolean IsCompleted() throws SecurityTokenException, CommandFailedException {
LoginToken.ValidateToken(this.getSecurityToken());
HttpsURLConnection conn = null;
Gson gson = (new GsonBuilder()).create();
String json;
try {
URL url = new URL(String.format("https://api.***.com/%1$s/detector/%2$s/status", new Object[]{"v1", this.getPID()}));
conn = ***Client.getClient(url, this.getSecurityToken(), RequestMethod.GET, "application/json", "text/plain");
Throwable response1;
BufferedInputStream inputStream;
if(conn.getResponseCode() != 200) {
response1 = null;
inputStream = null;
String response2;
try {
BufferedInputStream inputStream1 = new BufferedInputStream(conn.getErrorStream());
try {
response2 = HttpURLConnectionHelper.convertStreamToString(inputStream1);
} finally {
if(inputStream1 != null) {
inputStream1.close();
}
}
} catch (Throwable var41) {
if(response1 == null) {
response1 = var41;
} else if(response1 != var41) {
response1.addSuppressed(var41);
}
throw response1;
}
BadLoginResponse response4 = (BadLoginResponse)gson.fromJson(response2, BadLoginResponse.class);
if(response4 == null) {
throw new RuntimeException("Unable to process server response.");
}
throw new CommandFailedException(response4.getMessage(), conn.getResponseCode());
}
Throwable response = null;
response1 = null;
try {
inputStream = new BufferedInputStream(conn.getInputStream());
try {
json = HttpURLConnectionHelper.convertStreamToString(inputStream);
} finally {
if(inputStream != null) {
inputStream.close();
}
}
} catch (Throwable var43) {
if(response == null) {
response = var43;
} else if(response != var43) {
response.addSuppressed(var43);
}
throw response;
}
} catch (IOException var44) {
throw new RuntimeException(var44.getMessage());
} finally {
if(conn != null) {
conn.disconnect();
}
}
How can i fix it?
Thanks BNK!
The solution was to remove conn.setDoOutput(true)

Reading HttpURLConnection

I've been trying to figure out how to read a HttpURLConnection. According to this example: http://www.vogella.com/tutorials/AndroidNetworking/article.html , the following code should work. However, readStream never fires, and I'm not logging any lines.
I do get that the InputStream is passed through the buffer and all, but for me the logic breaks down in the readStream method, and then mostly the empty string 'line' and the while statement. What exactly is happening there / should happen there, and how would I be able to fix it? Also, why do I have to create the url in the Try statement? It gives back a Unhandled Exception; java.net.MalformedURLException.
Thanks in advance!
static String SendURL(){
try {
URL url = new URL("http://www.google.com/");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
readStream (con.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
return ("Done");
}
static void readStream(InputStream in) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
Log.i("Tag", line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
There are a bunch of things wrong with the code I posted in the question. Here is a working example:
public class GooglePlaces extends AsyncTask {
public InputStream inputStream;
public GooglePlaces(Context context) {
String url = "https://www.google.com";
try {
HttpRequest httpRequest = requestFactory.buildGetRequest(new GenericUrl(url));
HttpResponse httpResponse = httpRequest.execute();
inputStream = httpResponse.getContent();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
try {
for (String line = null; (line = bufferedReader.readLine()) != null;) {
builder.append(line).append("\n");
Log.i("GooglePlacesTag", line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
It appears you are not connecting your HTTPUrlClient try con.connect()

Categories