 |
AJAX I18n with Java
Posted by gmurray71 on March 13, 2006 at 04:13 PM | Comments (7)
Internationalization (i18n) is easy if you are using AJAX and Java. Both Java and JavaScript have i18n capabilities though it is not obvious how to use those capabilities are not from an i18n background.
I have re-worked the Realtime Validation with AJAX example to be i18n enabled. Follow these steps on the client and server to support i18n.
On the client:
- Set the content-type in your pages to UTF-8
UTF-8 is the recommended encoding as it supports the widest range of languages.
- From JavaScript call encodeURIComponent() on localized form parameters.
This is a built in JavaScript function that will make sure form variables are encoded in an HTTP friendly way. The encoding scheme used matches the charset used in the content-type of the page.
The following JavaScript snippet gathers form information to send back to the server in an AJAX request. Note the sections marked in red.
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript">
...
function validateUserId() {
if (!target) target = document.getElementById("userid");
var url = "validate?id=" + encodeURIComponent(target.value);
var target = document.getElementById("userid");
var ajax = new AJAXInteraction(url, validationCallback);
ajax.doGet();
}
function validateCallback(responseXML) {
var msg = responseXML.getElementsByTagName("valid")[0].firstChild.nodeValue;
if (msg == "false"){
var mdiv = document.getElementById("userIdMessage");
// set the style on the div to invalid
mdiv.className = "bp_invalid";
mdiv.innerHTML = "Invalid User Id";
var submitBtn = document.getElementById("submit_btn");
submitBtn.disabled = true;
} else {
var mdiv = document.getElementById("userIdMessage");
// set the style on the div to valid
mdiv.className = "bp_valid";
mdiv.innerHTML = "Valid User Id";
var submitBtn = document.getElementById("submit_btn");
submitBtn.disabled = false;
}
}
</script>
...
<input type="text"
size="20"
id="userid"
name="id"
autocomplete="off"
onkeyup="validateUserId()">
<div id="userIdMessage"></div>
On the server:
- Call request.setCharacterEncoding("UTF-8") before getting any parameters.
We know this is the correct encoding because we set it as the content type of the page.
- Set the content-type on the response to "UTF-8" if it contains localized content.
Event though the defualt encoding of XML is UTF-8 don't assume the conent will be encoded in UTF-8. Set the response content type using the servlet method response.setContentType where the content-type is followed by the encoding used for the response. In this case use "charset=UTF-8".
The following servlet interacts with an internationalized AJAX client. Once again the i18n specific portions are marked in red.
public class ValidationServlet extends HttpServlet {
private ServletContext context;
private HashMap accounts = new HashMap();
public void init(ServletConfig config) throws ServletException {
super.init(config);
this.context = config.getServletContext();
accounts.put("greg","account data");
accounts.put("duke","account data");
// add a Japanese hiragana example "ne" "ko" (cat)
accounts.put("\u306D\u3053","account data");
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
String targetId = request.getParameter("id");
if ((targetId != null) && !accounts.containsKey(targetId.trim())) {
response.setContentType("text/xml;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write("<valid>true</valid>");
} else {
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write("<valid>false</valid>");
}
}
}
That is pretty much it. This example the Japanese hiragana characters
"ねこ" are a reserved user id. The image below shows the example running.
Find the code and more about this example at Realtime Validation with AJAX.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Hi Greg. I've been looking around for a good AJAX tutorial for a while.
Yours is okay, but needs a little work to make it clearer.
The line "var ajax = new AJAXInteraction(url, processRequest);" doesn't match the example, where it says "var ajax = new AJAXInteraction(url, validateCallback);"
This was more than a little confusing reading through the example, because I kept wondering why process request would call itself again after it was successful. Actually, now that I look at it, it looks like the document:
design.html
Is out of date with the code samples
index.jsp
and
ValidationServlet.java
... the main differences being in the validateUser, initRequest and processRequest functions.
The UML picture is a help, I think after the ValidationServlet returns its XML it would be helpful to have a line from XMLHTTPRequest back to itself saying something like "state changes". Or, if I'm wrong, then that needs clarification.
I was wondering about the difference in the servlet between the get and the post, but that was answered by the time I got to the bottom of the explanation page. It makes me wonder whether there is some fundamental requirement that means you have to double up on the same servlet, or could you have split the ajax part off into its own dedicated servlet? (And even if you could, perhaps you wouldn't want to, but if not, then why not? (In your example the answer is that both of them would need to share the hashmap of ids anyway)). I like to have many simple servlets, part of that whole divide and conquer thing.
Oh yes, and I was wondering about the Sun microsystems copyright notice, do you work at Sun?
Posted by: rickcarson on March 16, 2006 at 05:37 AM
-
Also, it doesn't look like the functions: setMessageUsingDOM and setMessageUsingInline are called from the client side?
If not, then they should probably be removed from the example?
Posted by: rickcarson on March 16, 2006 at 05:42 AM
-
The design documents are a little out of sync and they do need updating. I will see what I can do about getting the update done today. I will also look at renaming the callback method in the blog example.
The validation example does both validation checking (doGet) and it also puts information in the HttpSession (doPost) when the form is submitted. The second page of the application requires the information in the HttpSession. These two methods could have been done by two separate servlets but in either case the updating of data on the server would have been done using a doPost. The examples aren't together in the same servlet for the Hashmap. In a more complete example this data would be stored in a database.
Regarding the setMessageUsingDOM and setMessageUsingInline. I have hopes of using this example to showcase the two DHTML techniques for updating a document. I agree this might provide confusing and will remove these for now.
Oh and I do work at Sun...I've been at Sun since 97.
Posted by: gmurray71 on March 16, 2006 at 07:58 AM
-
hi greg;
I hope that you can help me.... I don understand this "var url = "validate?id=" + escape(idField.value);" How the url "validate" refers to validateservlet? can you explain me this? Please
Thanks.
Posted by: mauled666 on March 22, 2006 at 02:44 PM
-
"validate" is a relative URL that is mapped to ValidateServlet in the web.xml of the application.
Validates Form Input using XmlHttpRequest Objects
ValidationServlet
com.sun.j2ee.blueprints.bpcatalog.ajax.ValidationServlet
ValidationServlet
/validate
Posted by: gmurray71 on March 24, 2006 at 12:04 AM
-
"validate" is a relative URL that is mapped to ValidateServlet in the web.xml of the application.
<servlet>
<description>Validates Form Input using XmlHttpRequest Objects</description>
<servlet-name>ValidationServlet</servlet-name>
<servlet-class>com.sun.j2ee.blueprints.bpcatalog.ajax.ValidationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ValidationServlet</servlet-name>
<url-pattern>/validate</url-pattern>
</servlet-mapping>
Posted by: gmurray71 on March 24, 2006 at 12:05 AM
-
Greg, I have tried to add JDBC code to place my result set into the hashmap.
I keep getting error of NullPointerException.
In what way do you recommend adding JDBC to this example?
mike
mc1392@columbia.edu
Posted by: mc1392 on July 19, 2007 at 12:50 PM
|