package transactions;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SimpleTimeZone;
import java.util.logging.Logger;
import javax.servlet.http.*;
import com.google.appengine.api.datastore.DatastoreFailureException;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Transaction;
@SuppressWarnings("serial")
public class TransactionsServlet extends HttpServlet {
private static final Logger log = Logger.getLogger(TransactionsServlet.class.getName());
// Hard code the message board name for simplicity. Could support
// multiple boards by getting this from the URL.
private String boardName = "messageBoard";
public static String escapeHtmlChars(String inStr) {
return inStr.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">");
}
public void doGet(HttpServletRequest req,
HttpServletResponse resp)
throws IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
// Display information about a message board and its messages.
Key boardKey = KeyFactory.createKey("MessageBoard", boardName);
try {
Entity messageBoard = ds.get(boardKey);
long count = (Long) messageBoard.getProperty("count");
resp.getWriter().println("<p>Latest messages posted to " +
boardName + " (" + count + " total):</p>");
Query q = new Query("Message", boardKey);
PreparedQuery pq = ds.prepare(q);
for (Entity result : pq.asIterable()) {
resp.getWriter().println(
"<h3>"
+ escapeHtmlChars((String) result.getProperty("message_title"))
+ "</h3></p>"
+ escapeHtmlChars((String) result.getProperty("message_text"))
+ "</p>");
}
} catch (EntityNotFoundException e) {
resp.getWriter().println("<p>No messages.</p>");
}
// Display a web form for creating new messages.
resp.getWriter().println(
"<p>Post a message:</p>" +
"<form action=\"/\" method=\"POST\">" +
"<label for=\"title\">Title:</label>" +
"<input type=\"text\" name=\"title\" id=\"title\" /><br />" +
"<label for=\"body\">Message:</label>" +
"<textarea name=\"body\" id=\"body\"></textarea><br />" +
"<input type=\"submit\" />" +
"</form>");
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSSSS");
fmt.setTimeZone(new SimpleTimeZone(0, ""));
out.println("<p>The time is: " + fmt.format(new Date()) + "</p>");
}
public void doPost(HttpServletRequest req,
HttpServletResponse resp)
throws IOException {
// Save the message and update the board count in a
// transaction, retrying up to 3 times.
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
String messageTitle = req.getParameter("title");
String messageText = req.getParameter("body");
Date postDate = new Date();
int retries = 3;
boolean success = false;
while (!success && retries > 0) {
--retries;
try {
Transaction txn = ds.beginTransaction();
Key boardKey;
Entity messageBoard;
try {
boardKey = KeyFactory.createKey("MessageBoard", boardName);
messageBoard = ds.get(boardKey);
} catch (EntityNotFoundException e) {
messageBoard = new Entity("MessageBoard", boardName);
messageBoard.setProperty("count", 0L);
boardKey = ds.put(messageBoard);
}
Entity message = new Entity("Message", boardKey);
message.setProperty("message_title", messageTitle);
message.setProperty("message_text", messageText);
message.setProperty("post_date", postDate);
ds.put(message);
long count = (Long) messageBoard.getProperty("count");
++count;
messageBoard.setProperty("count", count);
ds.put(messageBoard);
log.info("Posting msg, updating count to " + count +
"; " + retries + " retries remaining");
txn.commit();
// Break out of retry loop.
success = true;
} catch (DatastoreFailureException e) {
// Allow retry to occur.
}
}
if (!success) {
resp.getWriter().println
("<p>A new message could not be posted. Try again later." +
"<a href=\"/\">Return to the board.</a></p>");
} else {
resp.sendRedirect("/");
}
}
}