I have a javascript library that is sending a POST request to my Java servlet, but in the doPost method, I can't seem to get the contents of the request payload. In chrome Developer Tools, all the content is in the Request Payload section in the headers tab, and the content is there, and I know that the POST is being received by the doPost method, but it just comes up blank.
For the HttpServletRequest
object, what way can I get the data in the request payload?
Doing request.getParameter() or request.getAttributes()
both end up with no data
Simple answer:
Use getReader() to read the body of the request
More info:
There are two methods for reading the data in the body:
getReader() returns a BufferedReader that will allow you to read the body of the request.
getInputStream() returns a ServletInputStream if you need to read binary data.
Note from the docs: "[Either method] may be called to read the body, not both."
String payloadRequest = getBody(request);
Using this method
public static String getBody(HttpServletRequest request) throws IOException {
String body = null;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
return body;
}
You can use Buffer Reader from request to read
// Read from request
StringBuilder buffer = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
buffer.append(System.lineSeparator());
}
String data = buffer.toString()
Java 8 streams
String body = request.getReader().lines()
.reduce("", (accumulator, actual) -> accumulator + actual);
With Apache Commons IO you can do this in one line.
IOUtils.toString(request.getReader())
If the contents of the body are a string in Java 8 you can do:
String body = request.getReader().lines().collect(Collectors.joining());
If you are able to send the payload in JSON, this is a most convenient way to read the playload:
Example data class:
public class Person {
String firstName;
String lastName;
// Getters and setters ...
}
Example payload (request body):
{ "firstName" : "John", "lastName" : "Doe" }
Code to read payload in servlet (requires com.google.gson.*):
Person person = new Gson().fromJson(request.getReader(), Person.class);
That's all. Nice, easy and clean. Don't forget to set the content-type header to application/json.
Using Java 8 try with resources:
StringBuilder stringBuilder = new StringBuilder();
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
char[] charBuffer = new char[1024];
int bytesRead;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
}
You only need
request.getParameterMap()
for getting the POST and GET - Parameters.
The Method returns a Map<String,String[]>.
You can read the parameters in the Map by
Map<String, String[]> map = request.getParameterMap();
//Reading the Map
//Works for GET && POST Method
for(String paramName:map.keySet()) {
String[] paramValues = map.get(paramName);
//Get Values of Param Name
for(String valueOfParam:paramValues) {
//Output the Values
System.out.println("Value of Param with Name "+paramName+": "+valueOfParam);
}
}
Related
I'm with problem to parse a JSON. Always that I try do it, the follow was result is returned: Unexpected character () at position 0.
public Object execute(HttpRequestBase request){
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = null;
Object object = null;
try {
response = client.execute(request);
InputStream is = response.getEntity().getContent();
BufferedReader br = new BufferedReader(new InputStreamReader((is)));
StringBuilder builder = new StringBuilder();
String output;
while ((output = br.readLine()) != null) {
builder.append(output).append("\n");
}
if (response.getStatusLine().getStatusCode() == 200) {
object = new JSONParser().parse(builder.toString());
client.getConnectionManager().shutdown();
} else {
LOG.log(Level.SEVERE, builder.toString());
throw new RuntimeException(builder.toString());
}
} catch (IOException | ParseException ex) {
LOG.log(Level.SEVERE, ex.toString());
} finally {
}
return object;
}
PS:
My response returns a JSON well formatted;
The problem happens when this piece of code is running object = new JSONParser().parse(builder.toString());
The is part o my JSON file:
[
{
"id":2115,
"identificacao":"17\/2454634-6",
"ultima_atualizacao":null
},
{
"id":2251,
"identificacao":"17\/3052383-2",
"ultima_atualizacao":"2017-11-21"
},
{
"id":2258,
"identificacao":"17\/3070024-6",
"ultima_atualizacao":null
},
{
"id":2257,
"identificacao":"17\/3070453-5",
"ultima_atualizacao":null
}
]
Most probably your content has some unprinted special character at beginning. For UTF-8 encoded data this may be a BOM.
Please post start of you content as byte[].
It is happening because of UTF-8 BOM.
What is UTF-8 BOM ?
The UTF-8 BOM is a sequence of bytes (EF BB BF) that allows the reader to identify a file as being encoded in UTF-8.
Normally, the BOM is used to signal the endianness of an encoding, but since endianness is irrelevant to UTF-8, the BOM is unnecessary.
How to solve the issue ?
Convert encoding of your .json or any file to UTF-8 instead of UTF-8 BOM.
Like this.
Use this instead of BufferReader
Map<String,Object> result
= (Map<String,Object>)JSONValue.parse(IOUtils.toString(response.getEntity().getContent(), "utf-8"));
You will get your JsonData into Map and simply you can iterate over map.
I believe your problem is with the content-type. Use something like this:
HttpEntity content = response.getEntity();
StringBuilder sb = new StringBuilder();
InputStream is = content.getContent();
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
int character;
do {
character = isr.read();
if (character >= 0) {
sb.append((char) character);
}
} while (character >= 0);
return sb.toString();
No need for BufferedReader, InputStreamReader can handle it fine.
Hope it helps!
I found the problem!
My JSON was returning a different space character, so I did add it in my code this::
String content = builder.toString();
content = content.replaceAll("\\uFEFF", "");
This \uFEFF was my problem! And in my Dev environment it is not happens, just in production env!
I am having a very weird issue.
I am putting and getting messages from Amazon AWS SQS.
While putting I am compressing and encoding the messages, like this :
String responseMessageBodyOriginal = gson.toJson(responseData);
String responseMessageBodyCompressed = compressToBase64String(responseMessageBodyOriginal);
AmazonSqsHelper.sendMessage(responseMessageBodyCompressed, queue, null);
Compression and encoding function, looks like this :
public static String compressToBase64String(String data) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
GZIPOutputStream gzip = new GZIPOutputStream(bos);
gzip.write(data.getBytes());
gzip.close();
byte[] compressedBytes = bos.toByteArray();
bos.close();
return new String(Base64.encodeBase64(compressedBytes));
}
On the other hand, while receiving message, this is the code :
List<Message> sqsMessageList = AmazonSqsHelper.receiveMessages(queueUrl, max_message_read_count,
default_visibility_timeout);
int num_messages = sqsMessageList.size();
if (num_messages > 0) {
for (Message m : sqsMessageList) {
String responseMessageBodyCompressed = m.getBody();
String responseMessageBodyOriginal = decompressFromBase64String(responseMessageBodyCompressed);
}
}
And the function used for decoding and unzipping is like this :
public static String decompressFromBase64String(String compressedString) throws IOException {
byte[] compressedBytes = Base64.decodeBase64(compressedString);
ByteArrayInputStream bis = new ByteArrayInputStream(compressedBytes);
GZIPInputStream gis = new GZIPInputStream(bis);
BufferedReader br = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
gis.close();
bis.close();
return sb.toString();
}
But the problem is , at times if I pass characters like "â®" then those are getting converted to ???? , after decoding if I am printing the message.
Not able to figure out why encoding and decoding is behaving weird. Any help would be appreciated.
Issue is that encoding is done using the platform's default charset (data.getBytes()), while decoding - using UTF-8.
In compressToBase64String change data.getBytes() to data.getBytes(StandardCharsets.UTF_8).
I am creating this method which takes an InputStream as parameter, but the readLine() function is returning null. While debugging, inputstream is not empty.
else if (requestedMessage instanceof BytesMessage) {
BytesMessage bytesMessage = (BytesMessage) requestedMessage;
byte[] sourceBytes = new byte[(int) bytesMessage.getBodyLength()];
bytesMessage.readBytes(sourceBytes);
String strFileContent = new String(sourceBytes);
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(sourceBytes);
InputStream inputStrm = (InputStream) byteInputStream;
processMessage(inputStrm, requestedMessage);
}
public void processMessage(InputStream inputStrm, javax.jms.Message requestedMessage) {
String externalmessage = tradeEntryTrsMessageHandler.convertInputStringToString(inputStrm);
}
public String convertInputStringToString(InputStream inputStream) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
return sb.toString();
}
Kindly try this,
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
i believe that raw data as it is taken is not formatted to follow a character set. so by mentioning UTF-8 (U from Universal Character Set + Transformation Format—8-bit might help
Are you sure you are initializing and passing a valid InputStream to the function?
Also, just FYI maybe you were trying to name your function convertInputStreamToString instead of convertInputStringToString?
Here are two other ways of converting your InputStream to String, try these maybe?
1.
String theString = IOUtils.toString(inputStream, encoding);
2.
public String convertInputStringToString(InputStream is) {
java.util.Scanner s = new java.util.Scanner(is, encoding).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
EDIT:
You needn't explicitly convert ByteArrayInputStream to InputStream. You could do directly:
InputStream inputStrm = new ByteArrayInputStream(sourceBytes);
The getRequestBody method of the HttpExchange object returns an InputStream. There is still much work for correctly read the "Body". Is it a Java library + object + method that goes one more step ahead and returns the body (at the server side) as a ready-to-use Java String?
InputStreamReader isr = new InputStreamReader(t.getRequestBody(),"utf-8");
BufferedReader br = new BufferedReader(isr);
// From now on, the right way of moving from bytes to utf-8 characters:
int b;
StringBuilder buf = new StringBuilder(512);
while ((b = br.read()) != -1) {
buf.append((char) b);
}
br.close();
isr.close();
// The resulting string is: buf.toString()
// and the number of BYTES (not utf-8 characters) from the body is: buf.length()
If you are using Spring MVC, you can use the #RequestBody annotation on a method parameter which is of type String. For example.
#RequestMapping(value = "/something", method = RequestMethod.POST)
public void doSomething(#RequestBody String requestBodyString) {
// does something..
}
You can use Commons IO's org.apache.commons.io.IOUtils.toString(InputStream, String) to do this in one line. (It might not work with HTTP keep-alive though)
Edit:
If you want to go straight to JSON, there are a bunch of Web Service stacks that will do the unmarshalling for you. Try
Spring: http://www.cribbstechnologies.com/2011/04/08/spring-mvc-ajax-web-services-part-2-attack-of-the-json-post/
CXF / JAX-RS: http://cxf.apache.org/docs/jax-rs-data-bindings.html#JAX-RSDataBindings-JSONsupport
Did you try this ?
InputStreamReader isr = new InputStreamReader(exchange.getRequestBody(),"utf-8");
BufferedReader br = new BufferedReader(isr);
String value = br.readLine();
In HttpHandler:
InputStreamReader isr = new InputStreamReader(he.getRequestBody(), "utf-8");
BufferedReader br = new BufferedReader(isr);
int b;
StringBuilder buf = new StringBuilder();
while ((b = br.read()) != -1) {
buf.append((char) b);
}
br.close();
isr.close();
System.out.println(buf.toString());
I'm writing a little Java app which implements an http service that receives http post commands from a client.
The class I'm using to implement all of this is HttpHandler and HttpServer in the com.sun.net. package.
Now I'm implementing an handle(HttpExchange exchange) function which handles the request, and I'm having truble reading the post values received by the request because the only access that I have to these values is via HttpExchange.getResponseBody() which is just an output stream.
I'm looking to parse text post values and uploaded files.
I have written classes that process multipart requests for my project Sceye-Fi, an HTTP server that uses the com.sun.net.httpserver classes that come with java 6, to receive photo uploads from an Eye-Fi card.
This can help with file uploads (multipart posts).
For a non-multipart post, you would need to do something like this:
// determine encoding
Headers reqHeaders = exchange.getRequestHeaders();
String contentType = reqHeaders.getFirst("Content-Type");
String encoding = "ISO-8859-1";
if (contentType != null) {
Map<String,String> parms = ValueParser.parse(contentType);
if (parms.containsKey("charset")) {
encoding = parms.get("charset");
}
}
// read the query string from the request body
String qry;
InputStream in = exchange.getRequestBody();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte buf[] = new byte[4096];
for (int n = in.read(buf); n > 0; n = in.read(buf)) {
out.write(buf, 0, n);
}
qry = new String(out.toByteArray(), encoding);
} finally {
in.close();
}
// parse the query
Map<String,List<String>> parms = new HashMap<String,List<String>>();
String defs[] = qry.split("[&]");
for (String def: defs) {
int ix = def.indexOf('=');
String name;
String value;
if (ix < 0) {
name = URLDecoder.decode(def, encoding);
value = "";
} else {
name = URLDecoder.decode(def.substring(0, ix), encoding);
value = URLDecoder.decode(def.substring(ix+1), encoding);
}
List<String> list = parms.get(name);
if (list == null) {
list = new ArrayList<String>();
parms.put(name, list);
}
list.add(value);
}
An alternative would be using HttpService from HttpCore.
There is a Basic HTTP server example in the documentation