Wednesday, September 26, 2007

Order of Elements in web.xml

Till today I have been thinking that the elements in the deployment descriptor (web.xml) need to be in a specific order.

But on checking the servlet specification I found an interesting point. The DTDs (i.e Servlet version 2.2 and 2.3) define the elements in a sequential fashion. But the Servlet version 2.4 which defines an XSD is more liberal and allows all the root but next elements, i.e, direct child of <web-app> element, to be in any order.

So, now we can have <servlet> anywhere inside <web-app> element.

References: Web.xml XSD, SRV 13.2 in Servlet 2.4 Specification

Tuesday, September 25, 2007

Calling Java servlet from another Servlet/Jsp behind SSO

The issue can be viewed by breaking the problem into two parts.
1) How to make a call to a servlet from another servlet?
2) What if the servlet is SSO protected?

To understand the answer to the first question, we have to be aware that we are trying to call a servlet and not any Java API or a stand-alone class having main method. Ok, there is a way to call another servlet using Request Dispatcher, but what if you don't want to lose the control.

For eg:
1st Scenario: Servlet1 wants the service of Servlet2, and then use the results from Servlet2 for further processing.
2nd Scenario: Servlet1 wants to initialize an asynchronous service exposed as a servlet, Servlet2.

So, to call another servlet we will make use of java.net.* package. The concept is simple, create a new HTTP request in Servlet1 and send this HTTP request to Servlet2. So, to create this HTTP request we can use the java.net.* package.

The other aspect of the problem is how to call the servlet, if it is SSO protected. To bypass the SSO authentication while calling Servlet2 we can extract the authentication information from the Servlet1 request. Since all the authentication information is passed from client-side to the servlets in the form of cookies, we can extract these cookies from the Servlet1 request and include them in the new HTTP request that we are creating for Servlet2.

So, that is all about how and why. Now, check the code below which is calling a servlet from another servlet, without transferring the control and are SSO protected.

String cookieStr = "";
javax.servlet.http.Cookie cookies[] = request.getCookies();
for( int i=0; i<cookies.length; i++) {
javax.servlet.http.Cookie cookie = cookies[i];
String name = cookie.getName();
String value = cookie.getValue();
if(!"JSESSIONID".equals(name)) {
cookieStr += name;
cookieStr += "=";
cookieStr += value;
if(i != cookies.length -1) {
cookieStr += "; ";
}
}
}

StringBuffer mesg = new StringBuffer();
java.net.URL url = new java.net.URL("http://localhost:8080/App1/Servlet2");

java.net.URLConnection urlCon = url.openConnection();
urlCon.setRequestProperty("Cookie", cookieStr);
urlCon.connect();
java.io.InputStream is = urlCon.getInputStream();
int b;
while( (b = is.read() ) != -1) {
out.write(b);
}

Dynamic Table in IE


Problem

Display a dynamic table with in a <div> tag in IE using Javascript.

Non-working Solution

var divElement = document.getElementById("divId");

var tableElement = document.createElement("table");
tableElement.setAttribute("width", "100%");
var tableNode = divElement.appendChild(tableElement);

var trElement = document.createElement("tr");
var tdElement = document.createElement("td");
var trSubGroup = trSubGroup.appendChild(trElement);
var tdFirst = trSubGroup.appendChild(tdElement);
var textNode = document.createTextNode('text');
tdFirst.appendChild(textNode);

This snippet looks all good to display the table, but guess what, it works in Firefox but not in IE.

After a bit of looking around, I found the solution and the cause. IE does not recognize table which does not have <tbody> tag as the child node of <table>. Here, since we are creating dynamic table we have to include the <tbody> tag explicitly. Important to note is that for static tables IE automatically adds the <tbody> tag.

Working Solution

So, the revised code would look like this:

var divElement = document.getElementById("divId");
var tableElement = document.createElement("table");
tableElement.setAttribute("width", "100%");
var tableNode = divElement.appendChild(tableElement);

var tBodyNode = document.createElement("tbody");
var tbody = tableNode.appendChild(tBodyNode);

var trElement = document.createElement("tr");
var tdElement = document.createElement("td");
var trSubGroup = tbody.appendChild(trElement);
var tdFirst = trSubGroup.appendChild(tdElement);
var textNode = document.createTextNode('text');
tdFirst.appendChild(textNode);