AJAX In Action [104]
Mercury’s diameter has been updated, but two other updates have failed, and a reason has been given in each case. Our user has been informed of the problems (in a rather basic fashion using the alert() function) and can take remedial action. The server-side component that handles these requests needs to be able to break the request data into commands and assign each command to an appropriate handler object for processing. As each command is processed, the result will be written back to the HTTP response. A simple implementation of a Java servlet for handling this task is given in listing 5.15.
Listing 5.15 CommandServlet.java
public class CommandServlet extends HttpServlet {
private Map commandTypes=null;
public void init() throws ServletException {
ServletConfig config=getServletConfig();
commandTypes=new HashMap(); b
Configure handlers on startup
boolean more=true;
for(int counter=1;more;counter++){
String typeName=config.getInitParameter("type"+counter); String typeImpl=config.getInitParameter("impl"+counter); if (typeName==null || typeImpl==null){
more=false;
}else{
try{
Class cls=Class.forName(typeImpl);
commandTypes.put(typeName,cls);
}catch (ClassNotFoundException clanfex){
this.log(
Licensed to jonathan zheng Writing to the server 203 "couldn't resolve handler class name " +typeImpl); } } } } protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws IOException{ resp.setContentType("text/xml"); c Process a request Reader reader=req.getReader(); Writer writer=resp.getWriter(); try{ SAXBuilder builder=new SAXBuilder(false); Document doc=builder.build(reader); d Process XML data Element root=doc.getRootElement(); if ("commands".equals(root.getName())){ for(Iterator iter=root.getChildren("command").iterator(); iter.hasNext();){ Element el=(Element)(iter.next()); String type=el.getAttributeValue("type"); XMLCommandProcessor command=getCommand(type,writer); if (command!=null){ Element result=command.processXML(el); e Delegate to handler writer.write(result.toString()); } } }else{ sendError(writer, "incorrect document format - " +"expected top-level command tag"); } }catch (JDOMException jdomex){ sendError(writer,"unable to parse request document"); } } private XMLCommandProcessor getCommand (String type,Writer writer) throws IOException{ f Match handler to command XMLCommandProcessor cmd=null; Class cls=(Class)(commandTypes.get(type)); if (cls!=null){ try{ cmd=(XMLCommandProcessor)(cls.newInstance()); }catch (ClassCastException castex){ sendError(writer, "class "+cls.getName() +" is not a command"); Licensed to jonathan zheng 204 CHAPTER 5 The role of the server } catch (InstantiationException instex) { sendError(writer, "not able to create class "+cls.getName()); } catch (IllegalAccessException illex) { sendError(writer, "not allowed to create class "+cls.getName()); } }else{ sendError(writer,"no command type registered for "+type); } return cmd; }` private void sendError (Writer writer,String message) throws IOException{ writer.write(" } } The servlet maintains a map of XMLCommandProcessor objects that are configured here through the ServletConfig interface b. A more mature framework might provide its own XML config file. When processing an incoming POST request c, we use JDOM to parse the XML data d and then iterate through the The XMLCommandProcessor interface consists of a single method: public interface XMLCommandProcessor