Monday, January 21, 2008

Serving files from your GWT app.

Also there are other ways to make this trick, I found this implementation easiest.

So. I have a GWT app nicely running but at some point I faced a new requirement - application need to be able create files at server side and serve this files through client to the user, and requirement is that user browser should open "Save as" dialog after the user clicks on the link.

Okay, what I've done first? Since everything coded in GWT, I've immediately created servlet at the server side like:


import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FileServlet extends HttpServlet {

private static final long serialVersionUID = -4356636877078339046L;

byte[] bbuf = new byte[1024];

private static final String textFileName = "files/text.txt";

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String filename = textFileName;

try {
ServletOutputStream out = response.getOutputStream();
ServletContext context = getServletConfig().getServletContext();

File file = new File(context.getRealPath("") + "/" + filename);
String mimetype = context.getMimeType(filename);

response.setContentType((mimetype != null) ? mimetype : "application/octet-stream");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "attachement; filename=\"" + filename + "\"");

DataInputStream in = new DataInputStream(new FileInputStream(file));

int length;
while ((in != null) && ((length = in.read(bbuf)) != -1)) {
out.write(bbuf, 0, length);
}

in.close();
out.flush();
out.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

}


i.e. servlet which reads the file (hardcoded name here) and streams it to the client side of webapp, and mapped it in the web.xml as independent from GWT servlet named FileServer. In my app I had a button which "generates a file" so i've attached code to the the button listener:


RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, GWT.getModuleBaseURL() + "FileServer");

try {
rb.sendRequest("GetFile", new RequestCallback() {
public void onError(Request request, Throwable exception) {
Window.alert("Error getting file");
}

public void onResponseReceived(Request request, Response response) {
System.out.println("response Recieved");
}
});

} catch (RequestException e) {
e.printStackTrace();
}


while everything looks nice, nothing worked, by debugging I found that server gets the request and generates file, servlet streams the data, but no "Save As..." dialog appears... hmm... Than I wasted _a lot_ of time trying to fix this stuff until I got a point that my GET request is not the same GET request that hyperlink generates, so right solution on the client side is to create a hyperlink like follows:

new HTML("< \a href=\"/file-server-sample/FileServer\">Get a text file")

which queries same servlet and invokes proper dialog.
now it works, everybody happy :). Of course you can add parameters to you hyperlink and see those in servlet to alter file generation behavior.

Monday, August 20, 2007

Great tool for web development: Firebug.

Just want to share the tool I found: Get Firebug here. I just love it's ability to "Tweak CSS to perfection", "Visualize CSS metrics" along with Javascripts debug.

Sunday, August 19, 2007

Installing cygwin on Vista.

I've got new Dell with Vista installed on and tried to install Cygwin today. It didn't worked... Installer stuck at gnuplot.sh...

In order to move over this point I've had to use the get Sysinternals' Process Explorer to kill this sh process, than it stuck on tetex-tiny.sh, killed again, than post-texmf.sh killed. After that setup finished, I had to do some magic though:

> mkpasswd -l [-d] > /etc/passwd
> mkgroup -l [-d] > /etc/group


so, command line worked...
I added C:\cygwin\bin to Windows PATH
and had to do magic again to get X client running...


ash from cmd.exe
than ran rebaseall


seems to be working at least so far...

Monday, May 28, 2007

Some Recipes to Improve Your Google Web Toolkit Development

While struggling with GWT debugging and development I found a pretty good article which has a good reasoning why and how a GWT-based project could be divided into "independent" parts from the development perspective of view: Some Recipes to Improve Your Google Web Toolkit Development. Will try to follow these guidelines right after tomorrow.

Tuesday, May 15, 2007

Happy Coding Hour with Philip.

I missed all deadlines for making this post, but had a good reason, that I'll explain further:

So, back to the coding hour: it was just great. We worked on my GWT telemetryviewer, but most of the time we spent discussing and drawing on the board. Philip asks me questions that I wasn't able to answer and which forces me to learn more. I do appreciate this, it reminds me class teaching experience: you seems to know all, but student asks you are very "dumb" (in your opinion) question - ... and you are lost. You just can not answer straight, you are puzzled by a question because it so simple that it really cuts down to the bones of the subject through all the meat. That's it. I've learned the lesson: even if GWT claims that it hides all DOM and client-server interaction from the developer, I must have an idea how all this stuff works.

Wednesday, May 9, 2007

Happy coding with Hongbing.

During coding hour (in fact we spent about 90 min) we were working on the UI design today. We tried to follow my instructions about installing the environment and failed since GWT seems to keep absolute paths within its config and datafiles. We had to change hardcoded paths manually.
After stuff was installed and we got mockup working we were trying to understand the GWT hosted and compiled modes along with hosting the mockup within the Tomcat. This task turned out to be pretty difficult since I am using JFreeChart jar and servlet along with JCommon. Basically we gave up and proceeded further.
The last timeframe we spent discussing my UI design. Hongbing was developing HackyStat for a long time and helped me to figure out which way of abstractions would fit previous HackyStat architecture (I want reuse some code instead of hacking by myself). Overall this part was a most productive.

Saturday, May 5, 2007

Thinking Linux?

Okay, I was using SuSe for more than three years now, both Enterprise @HPC and Open @home. I like it, I think Novell rules, and would recommend it for everybody, but boy, there are only 2% females out there in the real life using SuSe??? Something wrong out there, because I have two females and two males in my family using SuSe, i.e. 50/50, WHat's up with others 27458 users taking the survey?