Reading JQuery data sent from Ajax in Java Servlet - java

Here is my Ajax code:
var myJSONObject = {"bindings": [
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}]
};
$.ajax({
url : "ships",
data : myJSONObject,
success : function(data){
GLOBAL.player.startShooting(data);
},
error : function(data) {
console.log("error:", data);
},
dataType : "json",
timeout : 30000,
type : "post"
});
And here is my Java Servlet code:
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("im in PSOT");
System.out.println(request.getParameter("myJSONObject"));
StringBuilder sb = new StringBuilder();
BufferedReader br = request.getReader();
String str;
while( (str = br.readLine()) != null ){
sb.append(str);
}
System.out.println(sb.toString());
response.setContentType("application/json");
response.getWriter().write("{\"key\":\"hello\",\"key2\":\"world\"}");
}
The Java servlet returns my Hello World object, but i CANNOT read data in Java Servlet
The console prints out the following:
im in PSOT
null
The last line is an empty string from last println.
I am using Tomcat 7
Can anyone please tell me what i am doing wrong and why i cannot read data in Java Servlet_

The parameter name is not myJSONObject. That's the JS variable name. The parameter names are all the root keys which you have there in your JSON object. E.g.
String bindings = request.getParameter("bindings");
// ...
You'd only need to manually parse it further. You could use Google Gson for this.
As to why the Reader didn't return anything, that's because the request body can be read and parsed only once. Any getParameter() call will implicitly do that. So when you call getParameter() before getReader(), you won't be able to read the request body by the Reader (the same applies for the other way round!). But you don't need it anyway. Just use getParameter() with the proper parameter names.

You'd only need to manually parse it further. You could use Google Gson for this.
As to why the Reader didn't return anything, that's because the request body can be read and parsed only once. Any getParameter() call will implicitly do that. So when you call getParameter() before getReader(), you won't be able to read the request body by the Reader (the same applies for the other way round!). But you don't need it anyway. Just use getParameter() with the proper parameter names.

Related

Respond to a Restful call

I am making a restful call to the servlet doGet() method from my grails code.The doGet() method is called successfully and i am able to see the print statements. Once the doGet() is called i need to send a response back to the restful call that the method has been invoked. How to set the response in the servlet so that it can be sent back to the grails
def getStatus(String tableName) {
try {
def result
def resultList = []
println "attempting to send START signal to http://localhost:9081/ServletSample/ServletSample"
result = rest.get("http://localhost:9081/ServletSample/ServletSample?tableName="+tableName)
println "length "+result.length()
println result.body
resultList.add(result)
log.debug "$result.body"
resultList.each {
println "$it.body"
if (it.status == 200) {
if (it.body == "Starting")
{
println ("starting up")
in the servlet i am trying to set the response as
response.setContentLength(5);
response.setStatus(200);
but it is not getting received. I am getting the following exception
Exception occured in rest service() groovy.lang.MissingMethodException: No signature of method: grails.plugins.rest.client.RestResponse.length() is applicable for argument types: () values: []
Possible solutions: getAt(java.lang.String), each(groovy.lang.Closure), with(groovy.lang.Closure), wait(), getXml(), every() from class java.net.URL
You need to convert java object into json string and write it into HttpServletResponse. Here is code:
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
// Get the printwriter object from response to write the required json object to the output stream
PrintWriter out = response.getWriter();
String json = new Gson().toJson(someObject);
out.write(json);
To convert java object into json string I used Google Gson
But you can manually create json string if it is easy

Send a List object from a Java Servlet to JSP using the PrintWriter object?

Before proceeding I realise that there's a similar question (Passing a List from Servlet to JSP) from a couple of years ago. I realise that it is possible to set the list I'm trying to pass as a session attribute but out of curiosity I wondered if it's possible to use the PrintWriter object to send the data back to the JSP page.
JSP
<script type="text/javascript">
function getEngineSchemes(engineID) {
$.get('SchemeTypeServlet', {
action: "getSchemes",
engineID: engineID
},
function(data, status){
}).fail(function() {
alert("Error obtaining schemes for engine with engine id: " + engineID);
});
}
</script>
</body>
Servlet
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Set type of response
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
//get parameters that may be passed from client to determine which methods should be called
String action = request.getParameter("action");
if(action.equalsIgnoreCase("getSchemesForEngine")) {
Integer engineID = Integer.parseInt(request.getParameter("engineID"));
List<String> schemeNames = getSchemeNamesForEngine(engineID);
response.getWriter(). //insert code to send object back to JSP
response.getWriter().flush();
}
Options
One solution I think may be reasonable would be to create a JSONObject and have something along the lines of
response.setContentType("application/json");
JSONObject json = new JSONObject();
for(String name : schemeNames) {
json.put(engineID, name);
}
response.getWriter().write(json.toJSONString());
response.getWriter().flush();
I haven't tested the above code but I just want to know if that seems like the best solution to my problem or if I'm making it overly complicated? Maybe there's a far simpler solution to my question.
I think you are having things messed up in your head. First of all, you cannot sent text or any kind of data from a servlet to a jsp. The proper way to do this is to use the session and use response.sendRedirect or RequestDispatcher.forward methods. But this will ignore any calls made before to the servlet's Writer Object.

Jobs are not returning valid WS.HttpResponse data with Play 1.4.0

I have jobs that return a WS.HttpResponse result like:
public class GetMessage extends Job<HttpResponse> {
...
public HttpResponse doJobWithResult() {
HttpResponse resp = WS.url(url).get();
return resp;
}
}
This is how I get the result from the job:
HttpResponse response = await(new GetMessage(params).now());
When I attempt to call getString() or getStream() using the "response" object I'm not getting any data.
If I call getString() in the job on "resp" then it has the data as expected.
It's strange because this worked with Play 1.2.4 - Play 1.2.7.2.
After the await I do have a non null "response" object and I can call getStatus() on it and it returns a 200, but maybe that's the default when WS.HttpResponse is initialized. I'm thinking that maybe I'm getting a new WS.HttpResponse() rather than the one returned from the job.
I found the problem. I was calling getString() to construct an error message that I would log if I got an error response. This was clearing the stream. I'm not sure why it worked the way it was in play <= 1.2.7.2.
Perhaps the InputStream should be closed and throw when calling getStream after getString or getStream have been called?

How to download file from httpServlet with Jquery?

In my application, a json object is created on client side. This object is posted to a HttpServlet which creates a pdf file based on the POST data.
The file is send back to the user. The succes function is called, and stream data is logged. I want however, that the file is downloaded.
How to achieve this?
My clientside code:
$(document).ready(function() {
// when the print button is clicked
$('#exportButton').click(function() {
var tableIdx = performanceDetailTableController.getTableIdx();
var allData = {
"shipTable1":{
"rows":[
{ "latitude":"12323","longitude":"213213"},
{ "latitude":"213213","longitude":"543543"}
]},
"shipTable2":{
"rows":[
{ "latitude":"12323", "longitude":"213213"},
{ "latitude":"213213","longitude":"543543"}
]}
}
var postData = JSON.stringify(allData);
$.ajax({
type : "POST",
url : 'pdfServlet',
contentType: "application/json; charset=utf-8",
data : postData,
async : false,
success : function(data) {
alert("got some data");
console.log(data);
},
});
});
});
And the servlet creating the file:
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// get the json content
StringBuffer jsonContent = getPostedContent(request);
log.info(jsonContent.toString());
// convert json to pojo's
Tables tables = getTablesFromString(jsonContent);
// create a xml stream
ByteArrayOutputStream xml = new XmlConverter().getXMLSource(tables);
// put the xml on the request
request = setXmlOnRequest(request, xml);
// create pdf data of the pdf-able xml content
ByteArrayOutputStream pdf = new PdfHandler().createPdfDataStream(request);
// response = createResponseheaders(response, request);
response.setContentType("application/pdf");
response.setContentLength(pdf.size());
response.setHeader("Content-disposition", "attachment; filename=test.pdf");
response.setCharacterEncoding("utf-8");
response.getOutputStream().write(pdf.toByteArray());
//close the streams
pdf.close();
response.getOutputStream().close();
}
The ouput in the log:
%PDF-1.4
%
4 0 obj
<<
/Producer (Apache FOP Version SVN branches/fop-0_95)
/CreationDate (D:20130725162007+02'00')
>>
endobj
5 0 obj
<<
/N 3
/Length 11 0 R
/Filter /FlateDecode
>>
stream
xwTSϽ7PhRHH.*1 J
*MY SOLUTION: *
see http://www.particletree.com/notebook/ajax-file-download-or-not/ for a pointer
I created a form with one hidden field:
<button id="exportButton">export</button>
<form id="exportForm" method="post" action="pdfServlet">
<input type="hidden" value="empty" id="pdf_data" name="pdf_data" />
</form>
than i changed my jquery post data controller to:
$('#exportButton').click(function() {
var tableIdx = performanceDetailTableController.getTableIdx();
var allData = {
"shipTable1":{
"rows":[
{ "latitude":"12323","longitude":"213213"},
{ "latitude":"213213","longitude":"543543"}
]},
"shipTable2":{
"rows":[
{ "latitude":"12323", "longitude":"213213"},
{ "latitude":"213213","longitude":"543543"}
]}
}
var postData = JSON.stringify(allData);
// put the data on the hidden form field in the export form
$('#pdf_data').val(postData);
// and submit the form
$('#exportForm').submit();
});
so now when i click the export button, the hidden field in the form gets the data to post and the data is posted as www-form encoded.
This way the servlet can handle the request and the the file is downloaded to the client.
You can't download files with ajax. JavaScript has for obvious security reasons no facilities to trigger a Save As dialogue with arbitrarily retrieved/generated content in JavaScript context. The world wide web would have looked very different if that was possible.
If you insist in using JS/jQuery for that, you need to send a synchronus GET request instead. You can do that with window.location (you only need to rename doPost() to doGet()).
window.location = 'pdfServlet?param1=value1&param2=value2';
Alternatively, just throw away all that unnecessary JS/jQuery and just use plain HTML <form action="pdfServlet" method="post"> with <input type="submit">. Additional bonus is that it works in browsers with JS disabled.
If your sole reason to grab ajax is actually a naive attempt to avoid the page being refreshed, then I can tell you that this really won't happen if the response has a Content-Disposition: attachment header. So that part is already safe.

multipart form data in javascript with java server using FileUpload

I try to send a multipart form data with a file by using only javascript. I write the request myself. So my javascript code is the following :
var data =
'------------f8n51w2QYCsvNftihodgfJ\n' +
'Content-Disposition: form-data; name="upload-id"\n' +
'\n' +
'uploadedFiles\n' +
'------------f8n51w2QYCsvNftihodgfJ\n' +
'Content-Disposition: form-data; name="file"; filename="doc1.txt"\n' +
'Content-Type: text/plain\n' +
'\n' +
'azerty\n' +
'------------f8n51w2QYCsvNftihodgfJ--\n';
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=----------f8n51w2QYCsvNftihodgfJ');
xhr.sendAsBinary(data);
I run this javascript on Firefox 18.
So i got a servlet on /upload. Here's the code :
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestContext request_context = new ServletRequestContext(request);
boolean is_multipart = ServletFileUpload.isMultipartContent(request_context);
if (is_multipart) {
FileUpload file_upload = new FileUpload(fileItemFactory);
List<FileItem> file_items = file_upload.parseRequest(request_context); // This line crash
}
}
As the comment says, the line file_upload.parseRequest(request_context); crash and throws the following exception :
org.apache.commons.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
at org.apache.commons.fileupload.MultipartStream.readHeaders(MultipartStream.java:539)
at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:976)
at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:942)
at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:349)
And i just don't know why i got this exception ... Any idea ?
It seems like MultipartStream can't find the request headers. But if i log the headers, they are all here and they are correct.
My servlet code works with a "normal" form. I tried to log the request body and headers of a normal form, and they are the same (except the boundary, of course).
I also tried to change the data variable with a invalid content. The error is still the same, so there's definitively a problem with my headers but i don't see what.
I found the solution.
\n IS NOT a valid separator for multipart form. You must use \r\n. Now my code works properly.
I don't understand why you use sendAsBinary. If not absolutely necessary I wouldn't assemble the payload (data variable) myself but use FormData.
https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects
var oMyForm = new FormData();
oMyForm.append("username", "Groucho");
oMyForm.append("accountnum", 123456); // number 123456 is immediately converted to string "123456"
// HTML file input user's choice...
oMyForm.append("userfile", fileInputElement.files[0]);
// JavaScript file-like object...
var oFileBody = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var oBlob = new Blob([oFileBody], { type: "text/xml"});
oMyForm.append("webmasterfile", oBlob);
var oReq = new XMLHttpRequest();
oReq.open("POST", "http://foo.com/submitform.php");
oReq.send(oMyForm);
try change f8n51w2QYCsvNftihodgfJ to f8n51w2QYCsvNftihodgfM
I've tried running your code with different random boundaries and turn out only f8n51w2QYCsvNftihodgfJ\n got issue. I reckon you can try a different boundary, since it is really just a random string.

Categories

Resources