|
The Guestbook ExampleNow for a somewhat more realistic example, a guestbook servlet. You can
run it in the same way as the previous example, except that you must also use
the Here's the template for the guestbook servlet: <html> <head> <title>Guestbook</title> </head> <body bgcolor="#E0E0FF"> <div align="center"> <font face="verdana,arial,helvetica" size="6" color="#191970"><b>Guestbook</b></font> </div> <br><br><br> <p> <if entryAdded> Thank you for your entry. <p><a href="GuestbookServlet">Add another entry</a> <else> Enter your name and message: <p> <form action="GuestbookServlet" method="post"> <input type="hidden" name="dataSubmitted" value="true"> <table border="0"> <tr> <td align="right">Name:</td> <td><input type="text" name="guestName" size="20"></td> </tr> <tr> <td align="right" valign="top">Message:</td> <td><textarea name="message" wrap="virtual" cols="50" rows="5"></textarea></td> </tr> </table> <p><input type="submit" value="Submit"> </if> <p> <hr> <p> <if guestbook> <table border="1" cellspacing="0" cellpadding="5" width="100%"> <tr> <td width="25%" align="center" bgcolor="#F0F0FF"> <font face="verdana,arial,helvetica" size="+1" color="#191970"> <b>Date</b> </font> </td> <td width="25%" align="center" bgcolor="#F0F0FF"> <font face="verdana,arial,helvetica" size="+1" color="#191970"> <b>Name</b> </font> </td> <td width="50%" align="center" bgcolor="#F0F0FF"> <font face="verdana,arial,helvetica" size="+1" color="#191970"> <b>Message</b> </font> </td> </tr> <list guestbook as entry> <tr> <td bgcolor="#F0F0FF" valign="top">${entry.date}</td> <td bgcolor="#F0F0FF" valign="top">${entry.name}<br></td> <td bgcolor="#F0F0FF" valign="top">${entry.message}<br></td> </tr> </list> </table> <br> <font size="-1"><i>First Entry:</i><br> Name is ${guestbook[0].name}<br> Message is ${guestbook[0].message}<br> Date is ${guestbook[0].date}<br> </font> <else> There are no guestbook entries. </if> </body> </html> The easiest way to make a template data model would be to have the servlet
store the guestbook entries in a We could take one of two approaches to designing our
An object that has named properties needs an adapter that implements
First, we'll need a generic model class import java.util.*; public class Guestbook { private List list = Collections.synchronizedList(new LinkedList()); public Guestbook() { } public void addEntry(String name, String message) { list.add(new GuestbookEntry(name, message)); } public List getList() { return list; } } import java.util.Date; public class GuestbookEntry { private Date date; private String name; private String message; public GuestbookEntry(String name, String message) { date = new Date(); this.name = name; this.message = message; } public Date getDate() { return date; } public String getName() { return name; } public String getMessage() { return message; } } We can now make the import freemarker.template.*; import java.util.*; public class GuestbookTM implements TemplateSequenceModel { private List entries; public GuestbookTM(Guestbook book) { this.entries = book.getList(); } public boolean isEmpty() throws TemplateModelException { return entries.isEmpty(); } public TemplateModel get(int i) throws TemplateModelException { if ((i >= 0) && (i < entries.size())) { return new GuestbookEntryTM((GuestbookEntry)entries.get(i)); } else { throw new TemplateModelException("Index out of range."); } } public int size() { return entries.size(); } } Our adapter for import freemarker.template.*; import java.util.Date; import java.util.TimeZone; import java.text.DateFormat; public class GuestbookEntryTM implements TemplateHashModel { private GuestbookEntry entry; private SimpleScalar date; private SimpleScalar name; private SimpleScalar message; public GuestbookEntryTM(GuestbookEntry entry) { this.entry = entry; } public TemplateModel get(String key) throws TemplateModelException { if (key.equals("date")) { return getDate(); } else if (key.equals("name")) { return getName(); } else if (key.equals("message")) { return getMessage(); } else { return null; } } private TemplateModel getDate() { if (date == null) { DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); date = new SimpleScalar(dateFormat.format(entry.getDate())); } return date; } private TemplateModel getName() { if (name == null) { name = new SimpleScalar(entry.getName()); } return name; } private TemplateModel getMessage() { if (message == null) { message = new SimpleScalar(entry.getMessage()); } return message; } public boolean isEmpty() throws TemplateModelException { return (entry == null); } } Our servlet will store its single template,
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import freemarker.template.*; public class GuestbookServlet extends HttpServlet { private Guestbook book; private FileTemplateCache templateCache; public void init(ServletConfig config) throws ServletException { super.init(config); templateCache = new FileTemplateCache(this.getClass()); book = new Guestbook(); } public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = (res.getOutputStream(); // Get the guestbook's template. Template template = templateCache.getTemplate("guestbook_template.html"); // Make the root node of the data model. SimpleHash modelRoot = new SimpleHash(); // If an entry was submitted, add it to the guestbook. if (req.getParameter("dataSubmitted") != null) { book.addEntry(req.getParameter("guestName"), req.getParameter("message")); modelRoot.put("entryAdded", new SimpleScalar(true)); } // Wrap the guestbook in a template model adapter. GuestbookTM bookTM = new GuestbookTM(book); modelRoot.put("guestbook", bookTM); // Process the template. try { template.process(modelRoot, out); } catch( TemplateException e ) { e.printStackTrace(out); // Failure case } out.close(); } public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { doGet(req, res); } public String getServletInfo() { return "Guestbook Servlet"; } } Note that there is now a target in the ant build script in the root of the FreeMarker distribution that builds a fmexamples.war file containing the Hello, World and guestbook examples. You simply type: ant war on the command line and it will build an fmexamples.war. You will deploy this by dropping the file into the appropriate directory. If you are using Tomcat, that is <TOMCAT_HOME>/webapps. Then, you should be able to run the servlet by opening the URL: http://localhost:8080/fmexamples/servlet/guestbook in a browser. The above URL assumes that you are running Tomcat in its default out-of-the-box configuration. For other servlet servers, you may have to change the above slightly. |
|