Wednesday, November 19, 2008

Reading HTTP Request Body in Servlet

Suppose you are writing a program using Java on Java EE platform to create a web application, dynamic web pages or Java Web Service, you probably come to the point that you need to read HTTP request body, especially if you want to use Servlet Filter to intercept and manipulate ServletRequest / HTTPServletRequest before it is served by targeted servlet / JSP.

Reading HTTP Body is easy. You can use either the following methods to get HTTP Request Body (HTTP Request Payload). Both methods is useful only with HTTP POST message. If you try to read HTTP GET body, you will not get anything (except a null String). This is because HTTP GET message has empty body.

getReader()
This method is defined in Interface ServletRequest. It returns a BufferedReader object. Here is an example on how to read HTTP Request Body using getReader() method.

// inside service(ServletRequest req, ServletResponse res)
// of a class that implements Servlet
// or
// inside doPost(HttpServletRequest req, HttpServletResponse resp)
// of a class that implements HTTPServlet

BufferedReader buff = req.getReader();
char[] buf = new char[4 * 1024]; // 4 KB char buffer
int len;
while ((len = reader.read(buf, 0, buf.length)) != -1) {
out.write(buf, 0, len);
}

getInputStream()
This method is defined in Interface ServletRequest. It returns ServletInputStream which is an InputStream object.

// inside service(ServletRequest req, ServletResponse res)
// of a class that implements Servlet
// or
// inside doPost(HttpServletRequest req, HttpServletResponse resp)
// of a class that implements HTTPServlet

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;
}
}
}
String body = stringBuilder.toString();
System.out.println(body);

Note that by reading HTTP Request Body by using either of the above method, you cannot read the body again. Also, you can only call getReader() or getInputStream() only once and not both; otherwise you will get IllegalStateException.

If you want to use getReader() or getInputStream() in Filter to intercept, manipulate or reconstruct HTTP Request Body, you must use ServletRequestWrapper to reconstruct or preserve HTTP Request Body. See ServletRequestWrapper example here.

Monday, November 17, 2008

Use Internet Explorer (IE) in Firefox

Quick Answer : Install Firefox Plugin - IE Tab.

Firefox is great but there are some web pages out there that Firefox cannot render the page properly. One of the cause is that some web pages use HTML code or some script that can be rendered by Internet Explorer. Such a very nice example comes from my university registration website.

REG CHULA is the nickname of the website as called by most students here.

This is actually a menu on the left side of the page seen on Firefox. Pretty messy, eh?

There are some solutions to this problem. 1. Use Internet Explorer (obviously!) 2. Since my friends and I are computer engineering students (Geeks!), we are pretty addicted to Firefox. My friend, Teerapap, developed a Firefox plugin called "FireRegChula". He wrote a script that can be run from Greasmonkey. This solves the problem from REG CHULA well.

But, if you want a true IE inside Firefox, you will need this plugin: IE Tab.

After you install and restart Firefox, notice the lower right corner Firefox logo. Click on it to switch to IE. Click again to switch back. You can also configure it to activate IE automatically for a preconfigured website.

Sunday, November 16, 2008

How to read and send Hotmail in Outlook

If you want to use Microsoft Outlook to connect to your Hotmail account, there are two ways to achive this. If the first one doesn't work, try the second one. (Personally, I think the second method provide more reliable connectivity with hotmail server, but you will need to install a plugin.)

First method

Microsoft Office Outlook, Outlook Express, Windows Live Mail already have a functionality to connect to any Windows Live mail accounts (@hotmail.com, @windowslive.com, @msn.com, etc.) It will use an HTTP as a protocol to connect to hotmail server. To read / get and send email from Outlook, follow these steps:

1. Open Microsoft Outlook. Open the menu "Tools" > "Account Settings". This will open a dialog box.


2. Click "New" in "E-mail" tab.
Fill in your name as it will appear on the top of every e-mail message you sent from Outlook later.
Then, fill in your email address such as someone@hotmail.com; follow by your account password.
Uncheck "Manually configure server settings or additional server types", if it is checked.

3. Click Next.
Outlook will try to establish to Hotmail server. If it fail, click retry. After failing twice, it will ask you to provide additional informaion for server settings. Just ignore it, click back to the step 2 above, retype your password and click next again.

Second Method

If the first method doesn't work or Outlook shows a message states that you need to pay for Hotmail Plus to let you use Outlook to access Hotmail, you will need Microsoft Office Outlook Connector.

As describe on Microsoft website
With Microsoft Office Outlook Connector, you can use Microsoft Office Outlook 2003 or Microsoft Office Outlook 2007 to access and manage your Microsoft Windows Live Hotmail or Microsoft Office Live Mail accounts, including e-mail messages and contacts for free!

Follow these steps.

1. If you already add your hotmail account to Outlook, I suggest you should delete it first.
Go to "Tools" > "Account Settings", then click on the email account and click delete.

2. Download and install Microsoft Office Outlook Connector. As of the time I write this article the current version can be found here. Please also check here for newer version. Don't forget to close Outlook before you install Outlook Connector.

3. Restart Microsoft Outlook.

4. Click "Outlook Connector" > "Add a new Account"



5. Fill up your information. Restart Outlook.

Tuesday, November 11, 2008

Searchable Java Documentation / javadoc

If you are a beginner starting to learn how to program in Java, you probably already used the plain HTML-framed javadoc avalable on Sun's website as an online and downloadable zip file. This HTML javadoc is useful but it doesn't really gives you an opprtunity to search it using keywords and index. Fortunately, an HTML help format is available. It lets you search the entire Java Documentation using keywords / class name / method. Very convenient!

Try it out here.

Convert String to InputStream

If you want to create InputStream from String in Java, the following code might help.

String text = "simple string";
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( text.getBytes());

Since ByteArrayInputStream is a concrete class extends from InputStream, you can instantiate it using the new keyword and use it in place where InputStream is expected i.e. use it as an argument passed to another method.

SOAP XML Schema

Recently, I have been working on a web service project which involves SOAP message processing. Something strange is that I cannot find SOAP schema posted anywhere on the web. I tried googling "soap schema" and "soap xml schema" but found nothing. Anyway , I managed to get it from the WSDL message generated automatically when I created a web service using JAX-WS and NetBeans IDE 6.1. If anyone wanted to get a soap schema, here it is.

http://schemas.xmlsoap.org/soap/envelope/

Updated: I have just found some other schema.

Try googling "soap envelope schema".
http://www.google.com/search?q=soap+envelope+schema

and at W3C Schools

http://www.w3schools.com/soap/soap_syntax.asp

Read a text file using java.util.Scanner

Scanner is a utility class that comes with Java SE since version 5.0. It lets you read a plain text file just like BufferReader, but more flexible. It can be customized so that you can read the contents line-by-line, word-by-word, or customized delimiter.

The readFileByLine method reads a plain text file one line at a time.

public static void readFileByLine(String fileName) {
try {
File file = new File(fileName);
Scanner scanner = new Scanner(file);
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}

The following method does the same as above except that it use a new line character as a delimiter.

public static void readFileByLine(String fileName) {
try {
Scanner scanner = new Scanner(new File(fileName));
scanner.useDelimiter(System.getProperty("line.separator"));
while (scanner.hasNext())
System.out.println(scanner.next());
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}

What if you want to read the entire text file at once? You can do so by setting the delimiter "\\z".

public static void readFileByLine(String fileName) {
try {
Scanner scanner = new Scanner(new File(fileName));
scanner.useDelimiter("\\z");
System.out.println(scanner.next());
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
scanner.useDelimiter("\\z"); means the same as
scanner.useDelimiter(Pattern.compile("\\z"));
By using the "\\z" delimiter, you can read the entire web page as an HTML string.

public static void readWebPage(String url) {
URLConnection connection;
try {
connection = new URL(url).openConnection();
Scanner scanner = new Scanner(connection.getInputStream());
scanner.useDelimiter("\\z");
String text = scanner.next();
System.out.println(text);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

You can also use Scanner to read a semi-structured text file which stores data separated by tabs, commas, or semi-colons. For more information read this.

Consult java.util.regex.Pattern javadoc for other delimiters.