Handle attachment in response with RequestBuilder in GWT - java

I am making a HTTP POST request from GWT Client to a HTTPServlet. This Servlet is creating a PDF file from request content and writing it to response stream.
Headers of the response stream are:
Content-Disposition: attachment; filename=report.pdf
I want to open this PDF in new window of the user's browser or prompt him to download it.
import com.google.gwt.http.client.*;
...
String url = "http://www.myserver.com/getData?type=3";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
try {
Request request = builder.sendRequest(data, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Couldn't connect to server (could be timeout, SOP violation, etc.)
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
// Process the response in response.getText()
// Window.open(url, "_blank", "");
} else {
// Handle the error. Can get the status text from response.getStatusText()
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
}
How should I handle response in onResponseRecieved?

I think in this case you should not use a single RequestBuilder AJAX call. You can rely on the default browser behavior by invoking a normal call and letting the browser handle the PDF response (displaying it with a PDF viewer plugin or opening a Save dialog).
There are several alternatives to achieving this:
If you can pass your data in a GET request (only possible for a small data volume) you can create the URL with the data as GET parameters and then open a new browser window with Window.open() passing the URL with data.
For larger amounts of data you can first POST your data with RequestBuilder to the server to store the data temporaly and in RequestCallback.onResponseReceived() open a new browser window with a short URL like above in alternative 1. On the server side you have to split the PDF generation servlet into two parts: a data store servlet with POST method (i.e. storing the data into the web session) and a PDF render servlet with GET method, which takes the data out of the session (and deleting it) and doesn't need large parameters.
Create a form with method POST, hidden fields for your data and the PDF generation servlet URL. Fill the hidden fields with your data and submit the form programmatically (i.e. FormPanel.submit()). If you create your FormPanel with a target name the browser opens a new window or uses the specified frame to handle the response.

On the client side, use an Anchor instead of a request builder and invoke the servlet directly
by using Window.Location.replace(URL.encode(formActionUrl));

Related

How to display data of MYSQL in java with using of AJAX

I have one table in mysql which has three field with data inserted. there are three fields in it which are as below.
i want to display this data on a web browser with using ajax in java.
i search on a net and find this below code are most useful
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/ajax_demo","root","");
PreparedStatement ps=con.prepareStatement("select * from ajax");
what are other things i have to implement for displaying output.
You need to do a AJAX request, the main code body for an ajax request is the following
request.onreadystatechange=handleResponse;
request.open(typeReq, url, true);
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
request.send(queryString);
typeReq is the type of the request: POST or GET.
url: the destination url address.
queryString: the set of data which you want to send.
handleResponse is a function to hanled the response. For example:
function handleResponse () {
if (request.readyState = 4) {
if (request.status = 200) {
var response = request.responseText;
//code to handle response
} else {
//code to handle errors
}
}
Now, you can use an API like prototype or jquery, it's easier.
I hope this information helps you.
Good Luck

Jquery AJAX Result data retrieve back to client side in velocity template

I have just created an AJAX request in velocity template and able to get request at .java file as below: (java file is extended for "JiraWebActionSupport" as webwork module).
var url = "PlanIssuesAction!IssuesPlanning.jspa";
jQuery.post(url,myJSONObject,function(result) {
alert('success');
})
.done(function() { alert("in done"); })
.fail(function() { alert("error"); })
.always(function() { alert("finished"); });
On the server side, in doIssuesPlanning method, able to get call and insert the posted data.
public String doIssuesPlanning() {
System.out.println("Success executed result appear"); //i want this value to be //retrieval at client side but it's not working. unable to receive at ajax response.
return getRedirect("PlanIssuesAction!default.jspa");
//return "result is success" //also tried instead of getRedirect ,used direct response //return but not worked, it capture at error in ajax response at client side.
}
Now I need to return the result data to the client side back at jquery "Result" parameter.
How can I achieve this? Currently, in "Result" object shows all HTML text and nothing else.
(i have set object above through - "System.out.println and expect to be retrieved at client side but not working).
Can you please let me know , what is wrong here.
Thank you.
Webwork jspa URLs return HTML since that is their purpose. Most AJAX calls would be to a REST resource that returns JSON. I'd define a new REST resource for this. More information at https://developer.atlassian.com/display/DOCS/Developing+a+REST+Service+Plugin

Asynchronous file upload in Spring

Here's what I'm doing. I want to upload multipart file via Ajax to my Spring web app. When the server receives the POST request, it creates a ticket number in the database. It then starts a thread that handles the actual file upload. The server then returns the ticket number.
I am using the CommonsMultipartResolver to handle the request and I have set the resolveLazily flag to true so that the Multipart isn't resolved right away.
So here's something along the lines of what I have
#Controller
public class myController{
#RequestMapping(value = "/upload", method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.OK)
#ResponseBody
public String upload(MultipartHttpServletRequest request, String fileName){
String ticket = dao.createUploadTicket(fileName);
Runnable run = new Runnable(){
#Override
public void run(){
dao.writeUpdate(ticket, "Getting data from request");
final MultipartFile file = request.getFile("theFile");
dao.writeUpdate(ticket, "Multipart file processed");
try {
dao.writeUpdate(ticket, "Saving file to disk");
file.transferTo(new File("/myDirectory"));
dao.writeUpdate(ticket, "File saved to disk");
}
catch(Exception e){
dao.writeUpdate(ticket, "File upload failed with the exception " + e.toString());
}
}
};
Thread t = new Thread(run);
t.start();
return ticket;
}
}
So the point here is that the ticket number can be used to get the progress updates. Say a large file is being uploaded. The client that made the file upload POST (say in this instance an Ajax request) can do it asynchronously and get back a ticket number. The client can the use that ticket number to determine the stage of the file upload and display information in another page.
One other use is that I can have an HTML page that makes a request to the server for all ticket numbers, then shows a "live" view of all the file uploads that are taking place on the server.
I haven't been able to get this to work because as soon as the controller returns, Spring calls cleanupMultipart() in the CommonsMultipartResolver. Since the resolveLazily flag is set to false, when cleanupMultipart() is called, it will begin to resolve and initialize the multipart files. This leads to a race condition between the call to "request.getFile("theFile");" in the runnable and the cleanupMultipart() call eventually leading to an exception.
Anyone have any ideas? Am I breaking some kind of HTTP contract here by wanting to do back-end asynchronous file handling.
HTTP request is already executed in its own thread, and client can make few request in parallel, asynchronously. So you don't need to start a new thread. Just save/process file as usual, in main thread. Just make 'async file upload' only on client side.
Also, you should send http response only when you've processed the input. I mean you can't read input header, make a http response, and continue reading data from the browser. Consume input -> Process it -> Send output, that how HTTP 1/1.1 protocols works.
If you need a ticket number to send to upload, you could create it before actual uploading, by using a two step upload, like:
Ajax GET request to get ticket number
POST a file content and ticket number (received from previous step)
+ ajax GET get current status for ticket, anytime later, async

redirect from http to https and back to http within java servlet

there are a bunch of links accessing my servlet without https
As the servlet is a generic form and the http urls are generated with an random id it is difficult to use modrewrite or something like that.
Therefore I modified my servlet with code like that:
//redirect to https
String sec = servletRequest.getParameter("Sec");
String qString = servletRequest.getQueryString();
if (StringUtils.isEmpty(sec)){
try {
HttpServletResponse rsp = request.getServletResponse(true);
String PORTAL_URL = l_aliasHelper.getPath(request);
rsp.sendRedirect("https://"+servletRequest.getServerName() +PORTAL_URL+"?" +qString+"&Sec=yes");
} catch (Exception e) {
e.printStackTrace();
}
}
Now this works fine!
But, what if I want back to http because I want to avoid nagging warnings about insecure elements on other pages.
So how do I redirect to http again after the user has submitted the form?
If everything worked well the user gets displayed a response with a success message under the same URL he started.
So the cycle goes like this:
http://<somedomain>/<anypath>?<anyid>
https://<somedomain>/<anypath>?<anyid>&Sec=yes
and now it should go back maybe with a step inbetween to
http://<somedomain>/<anypath>?<anyid> <- the success message should be
displayed here
the last method before the message is displayed is
sucessmessage.render(request,response)
request and response are both appserver component specific views on all request / response related matters. They have methods like:
getServletResponse
public HttpServletResponse getServletResponse(boolean answering)
Gets the original servlet response. Note: This should be accessed
in extraordinary cases only. If the parameter is set to true all
further content procession of the runtime will be skipped. This is
only available, if the request was initiated from a servlet based
connection.
So how can the response be manipulated in a way that the form is submitted secure, but the user can go on with http on the rest of the site afterwards.
It seems like you are trying to do too much in one place. Maybe the following break down will be easier:
Specify https in the URL for the action parameter in HTML form.
Create a ServletFilter class that uses ServletRequest.isSecure() to
make sure that requests to your form action actually came in over
https. This could also be in your action servlet, but making it a filter means you can reuse it. Just make sure the secure servlets have this filter set.
In your form action servlet, simply send a redirect to the
success page over http

Download dynamic file with GWT

I have a GWT page where user enter data (start date, end date, etc.), then this data goes to the server via RPC call. On the server I want to generate Excel report with POI and let user save that file on their local machine.
This is my test code to stream file back to the client but for some reason I think it does not know how to stream file to the client when I'm using RPC:
public class ReportsServiceImpl extends RemoteServiceServlet implements ReportsService {
public String myMethod(String s) {
File f = new File("/excelTestFile.xls");
String filename = f.getName();
int length = 0;
try {
HttpServletResponse resp = getThreadLocalResponse();
ServletOutputStream op = resp.getOutputStream();
ServletContext context = getServletConfig().getServletContext();
resp.setContentType("application/octet-stream");
resp.setContentLength((int) f.length());
resp.setHeader("Content-Disposition", "attachment; filename*=\"utf-8''" + filename + "");
byte[] bbuf = new byte[1024];
DataInputStream in = new DataInputStream(new FileInputStream(f));
while ((in != null) && ((length = in.read(bbuf)) != -1)) {
op.write(bbuf, 0, length);
}
in.close();
op.flush();
op.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
return "Server says: " + filename;
}
}
I've read somewhere on internet that you can't do file stream with RPC and I have to use Servlet for that. Is there any example of how to use Servlet and how to call that servlet from ReportsServiceImpl. Do I really need to make a servlet or it is possible to stream it back with my RPC?
You have to make a regular Servlet, you cannot stream binary data from ReportsServiceImpl. Also, there is no way to call the servlet from ReportsServiceImpl - your client code has to directly invoke the servlet.
On the client side, you'd have to create a normal anchor link with the parameters passed via the query string. Something like <a href="http://myserver.com/myservlet?parm1=value1&.."</a>.
On the server side, move your code to a standard Servlet, one that does NOT inherit from RemoteServiceServlet. Read the parameters from the request object, create the excel and send it back to the client. The browser will automatically popup the file download dialog box.
You can do that just using GWT RPC and Data URIs:
In your example, make your myMethod return the file content.
On the client side, format a Data URI with the file content received.
Use Window.open to open a file save dialog passing the formatted DataURI.
Take a look at this reference, to understand the Data URI usage:
Export to csv in jQuery
It's possible to get the binary data you want back through the RPC channel in a number of ways... uuencode, for instance. However, you would still have to get the browser to handle the file as a download.
And, based on your code, it appears that you are trying to trigger the standard browser mechanism for handling the given mime-type by modifying the response in the server so the browser will recognize it as a download... open a save dialog, for instance. To do that, you need to get the browser to make the request for you and you need the servlet there to handle the request. It can be done with rest urls, but ultimately you will need a serviet to do even that.
You need, in effect, to set a browser window URL to the URL that sends back the modified response object.
So this question (about streaming) is not really compatible with the code sample. One or the other (communication protocols or server-modified response object) approach has to be adjusted.
The easiest one to adjust is the communication method.

Categories