Send data in the doPost() response? - java

I am a complete beginner in web programming. I created an application with Eclipse Java EE and a Tomcat server running in localhost.
The goal of the application is to get information from a client and send back other information.
I developped a servlet and implement a doPost() method that works perfectly. I get information that I saved in a bean named USSDPull and write in a text file named log.txt.
public void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException{
USSDPull ussdpull = new USSDPull();
ussdpull.setUssdstring(request.getParameter("ussdstring"));
ussdpull.setSessionid(Integer.parseInt(request.getParameter("sessionid")));
ussdpull.setMsisdn(request.getParameter("msisdn"));
ussdpull.setUssdcode(request.getParameter("ussdcode"));
ussdpull.setEncoding(Integer.parseInt(request.getParameter("encoding")));
response.setContentType("text/text");
response.setCharacterEncoding( "UTF-8" );
PrintWriter out = response.getWriter();
out.flush();
out.println("POST received : " + ussdpull.getUssdstring()+" "+ussdpull.getSessionid()+" "+ussdpull.getMsisdn()+" "+ussdpull.getUssdcode()+" "+ussdpull.getEncoding());
//WRITE IN FILE
FileWriter fw = new FileWriter("D:/Users/Username/Documents/log.txt", true);
BufferedWriter output = new BufferedWriter(fw);
output.write(dateFormat.format(date)+";"+ussdpull.getUssdstring()+";"+ussdpull.getSessionid()+";"+ussdpull.getMsisdn()+";"+ussdpull.getUssdcode()+";"+ussdpull.getEncoding()+"\n");
output.flush();
output.close();
}
I need the servlet to send back 2 specific booleans and 1 string to the client. I don't know how to proceed. Is it possible to use the HttpServletResponse to send the data? Or do I need to find a way to "call" the doGet() method?

The HttpServletResponse itself doesn't give you a way to write data back to the client other than some headers, such as the response code.
However, it has a method called getOutputStream and a method getWriter() that give you resp. an OutputStream or a PrintWriter. You can use these to write data to the response.

Related

Sending response before processing in Java servlet

I have a Java Servlet application running on JBoss 4 and this application receives POST request from another service. I want to acknowledge back to this service before processing. Is it fine to do the following?
protected void doPost(HttpServletRequest req, HttpServletResponse res) {
readReceivedPOSTData();
//send response
PrintWriter out = res.getWriter();
out.print("ack");
out.close();
//Process
processData(); //takes long time
}
I appreciate your help. Thank you.
The basis is ok.
Just some tips:
Use an identifier in the request so you can check in the future the status of that request.
Start another thread to process the data or use a jms queue
remember that you can't write additional data to the response in the processData() method

Java Spring - dynamically generated csv file download response is hanging

On my company's site we have some tables that we need to export to a csv file.
There are some varying parameters, so the csv file needs to be dynamically created on request.
My problem is that after clicking to download, the response hangs, and waits for the whole file to be created (which can take some time) and only then downloads the entire file in one instant.
I'm using AngularJS, so I'm using window.location = <url_for_file_download> In order to make the browser download the file.
On the server side I'm using Java Spring and I've followed all the instructions I could find on the web in order to create a file download controller.
My controller code is something like this:
#RequestMapping(value = "http://yada.yada.yada/csv/myFile.csv", method = RequestMethod.GET)
public #ResponseBody
void getCustomers(HttpServletResponse response,
#RequestParam(required = false) String someParameters)
throws NotAuthorizedException, IOException {
// set headers
setHeaders(response);
// generate writer
CSVWriter write = generateWriter(response);
// get data
List<String[]> data = getData();
// write and flush and all that
.
.
.
}
My code for setting the response headers are:
response.setContentType("text/csv;charset=utf-8");
response.setHeader("Content-Disposition","attachment; filename=\"" + fileName + ".csv\"");
I've also tried adding the following headers:
response.setHeader("Transfer-Encoding", "Chunked");
response.setHeader("Content-Description", "File Transfer");
and I've also tried setting the Content-type to "application/octet-stream".
Notice that I don't add a Content-length header, since the file doesn't exist yet, and is being written on the fly.
For writing the csv file I'm using OpenCSV and my code is as follows:
OutputStream resOs = response.getOutputStream();
OutputStream buffOs = new BufferedOutputStream(resOs);
OutputStreamWriter outputWriter = new OutputStreamWriter(buffOs,"UTF-8");
CSVWriter writer = new CSVWriter(outputWriter);
I iterate over the data and write it like so:
for (String[] row: data) {
writer.writeNext(line);
}
(It's not exactly the code - but this is more or else what happens in the code)
And at the end I flush and close:
writer.flush();
writer.close();
I also tried flushing after each line I write.
So why isn't the file being transferred before it has all been written?
Why is my browser (Google chrome) downloading the file in one instant after waiting a long time? And how can I fix this.
I hope I've added enough code, if there's something missing just please tell me and I'll try to add it here.
Thank you so much in advance.
Can you try returning a null value in your java
return null ;
Or you can try below code also
1. Jquery code upon clicking the submit button
$(document).ready( function() {
$('#buttonName').click(function(e){
$("#formName").submit();
//alert("The file ready to be downloaded");
});
});
Your controller code
#RequestMapping(value="/name",method=RequestMethod.POST)
public ModelAndView downloadCSV(ModelMap model,HttpSession session,#ModelAttribute(value="Pojo") Pojo pojo
,HttpServletRequest request,HttpServletResponse response){
----------------some code----------------
response.setContentType("application/csv");
("application/unknown");
response.setHeader("content-disposition","attachment;filename =filename.csv");
ServletOutputStream writer = response.getOutputStream();
logger.info("downloading contents to csv");
writer.print("A");
writer.print(',');
writer.println("B");
for(int i=0;i<limit;i++){
writer.print(""+pojo.get(i).getA());
writer.print(',');
writer.print(pojo.get(i).getB());
writer.println();
}
writer.flush();
writer.close();
---------------some code-----------
return null;
}
Hope this helps
The Controller will wait for the response to be written before the response is send back to the client.
Here is a nice post with multiple approaches / options outlined
Downloading a file from spring controllers
This post talks about flushing the output periodically to help fasten the download.
how to download large files without memory issues in java
If all you are trying to do is let the user know that the file download is in progress and due soon, I think an Ajax progress status indicaor might be your solution.
Trigger the ajax call to the back-end to generate the file
Show progress indicator to the user while file is being generated server side
once response is available, file is presented to the user.
I think something similar is being explored here download file with ajax() POST Request via Spring MVC
Hope this helps!
Thanks,
Paul
I faced the same issue. The code that didn't work for me was
#RequestMapping(value = "/test")
public void test(HttpServletResponse response)
throws IOException, InterruptedException {
response.getOutputStream().println("Hello");
response.getOutputStream().flush();
Thread.sleep(2000);
response.getOutputStream().println("How");
response.getOutputStream().flush();
Thread.sleep(2000);
response.getOutputStream().println("are");
response.getOutputStream().flush();
Thread.sleep(2000);
response.getOutputStream().println("you");
response.getOutputStream().flush();
}
The culprit was ShallowEtagHeaderFilter. When this filter is enabled the response is sent in one chunk. When this filter is diabled the response is send in multiple chunks.
From this thread Tomcat does not flush the response buffer it looks like another possible culprit can be GzipFilter

Response/Request between Javascript/Java Servlet

I have a simple test client-server app. Client is html/javascript, server - Java Servlet
First of all I want to test request/response mechanism. Therefore I have used a simple code for cliet(jQuery):
$.get ("http://localhost:8081/TestProject/BasicServlet",
function(data) {
alert('Data:' +data);
}
);
And on the server side:
protected void doGet(HttpServletRequest req, HttpServletResponse res) ... {
String callBack = "TestCallback";
res.setContentType("text/html");
ServletOutputStream out = res.getOutputStream();
out.write(callBack.getBytes("UTF-8"));
out.flush();
}
So, Servlet catches request from client, but I have a problem with response, response header looks good, with character attributes, but I don't receive the callBack data
As response in Firebug I have 3 tabs, Header, Answer, HTML. Answer and HTML are empty
EDIT:
I have found a Problem: it was Access-Control-Allow-Origin violation.
Thanks for help !
As per the documentation in here
http://download.oracle.com/javaee/6/api/javax/servlet/ServletResponse.html#getOutputStream
is used for sending binary data. So my guess is that Content-Type header is set as some MIME type which is not recognized by jQuery. I suggest you check whether the Content-Type header is still "text/html" in the response using FireBug, or use
PrintWriter writer = res.getWriter();
writer.write(callBack);
writer.flush();
By the way, for sending textual data using PrintWriter is the recommended approach.
Try out.print() instead of out .write() you will get the response in your ajax call.

How to make a servlet interact with the API of a website and also store the XML response?

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String text = "some text";
response.setContentType("text/plain"); // Set content type of the response so that jQuery knows what it can expect.
response.setCharacterEncoding("UTF-8"); // You want world domination, huh?
response.getWriter().write(text); // Write response body.
}
If I use this servlet , where request variable will have the url of the API of the website . Then how do I capture the response ? I would want to know what is the code to do that , and is this the right way to go about it when trying to build a JSP page that deals with interacting with an API of a website and showing data ?
You're confusing things. The HttpServletRequest is the HTTP request which the client (the webbrowser) has made to reach the servlet. The HttpServletResponse is the response which you should use to send back the result to the client (the webbrowser).
If you want to fire a HTTP request programmatically, you should use java.net.URLConnection.
URLConnection connection = new URL("http://example.com").openConnection();
InputStream input = connection.getInputStream(); // This contains the response. You need to convert this to String or some bean and then display in JSP.
See also:
How to use java.net.URLConnection to fire and handle HTTP requests

How to send byte[] as pdf to browser in java web application?

In action method (JSF) i have something like below:
public String getFile() {
byte[] pdfData = ...
// how to return byte[] as file to web browser user ?
}
How to send byte[] as pdf to browser ?
In the action method you can obtain the HTTP servlet response from under the JSF hoods by ExternalContext#getResponse(). Then you need to set at least the HTTP Content-Type header to application/pdf and the HTTP Content-Disposition header to attachment (when you want to pop a Save As dialogue) or to inline (when you want to let the webbrowser handle the display itself). Finally, you need to ensure that you call FacesContext#responseComplete() afterwards to avoid IllegalStateExceptions flying around.
Kickoff example:
public void download() throws IOException {
// Prepare.
byte[] pdfData = getItSomehow();
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
// Initialize response.
response.reset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
response.setContentType("application/pdf"); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ServletContext#getMimeType() for auto-detection based on filename.
response.setHeader("Content-disposition", "attachment; filename=\"name.pdf\""); // The Save As popup magic is done here. You can give it any filename you want, this only won't work in MSIE, it will use current request URL as filename instead.
// Write file to response.
OutputStream output = response.getOutputStream();
output.write(pdfData);
output.close();
// Inform JSF to not take the response in hands.
facesContext.responseComplete(); // Important! Else JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}
That said, if you have the possibility to get the PDF content as an InputStream rather than a byte[], I would recommend to use that instead to save the webapp from memory hogs. You then just write it in the well-known InputStream-OutputStream loop the usual Java IO way.
You just have to set the mime type to application/x-pdf into your response. You can use the setContentType(String contentType) method to do this in the servlet case.
In JSF/JSP you could use this, before writing your response:
<%# page contentType="application/x-pdf" %>
and response.write(yourPDFDataAsBytes()); to write your data.
But I really advise you to use servlets in this case. JSF is used to render HTML views, not PDF or binary files.
With servlets you can use this :
public MyPdfServlet extends HttpServlet {
protected doGet(HttpServletRequest req, HttpServletResponse resp){
OutputStream os = resp.getOutputStream();
resp.setContentType("Application/x-pdf");
os.write(yourMethodToGetPdfAsByteArray());
}
}
Resources :
mimeapplication.net - pdf
Javadoc - ServletResponse
Javadoc - HttpServlet
When sending raw data to the browser using JSF, you need to extract the HttpServletResponse from the FacesContext.
Using the HttpServletResponse, you can send raw data to the browser using the standard IO API.
Here is a code sample:
public String getFile() {
byte[] pdfData = ...
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
OutputStream out = response.getOutputStream();
// Send data to out (ie, out.write(pdfData)).
}
Also, here are some other things you might want to consider:
Set the content type in the HttpServletResponse to inform the browser you're sending PDF data:
response.setContentType("application/pdf");
Inform the FacesContext that you sent data directly to the user, using the context.responseComplete() method. This prevents JSF from performing additional processing that is unnecessary.

Categories

Resources