diff --git a/managed_vms/async-rest/src/main/java/com/google/appengine/demos/DumpServlet.java b/managed_vms/async-rest/src/main/java/com/google/appengine/demos/DumpServlet.java
new file mode 100644
index 00000000000..87012af49cd
--- /dev/null
+++ b/managed_vms/async-rest/src/main/java/com/google/appengine/demos/DumpServlet.java
@@ -0,0 +1,60 @@
+package com.google.appengine.demos;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Collections;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@SuppressWarnings("serial")
+public class DumpServlet extends HttpServlet {
+
+ @Override
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException,
+ IOException {
+ response.setContentType("text/html");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ PrintWriter out = response.getWriter();
+
+ out.println("DumpServlet
");
+ out.println("Context Fields:
");
+ out.println("");
+ out.printf("serverInfo=%s%n", getServletContext().getServerInfo());
+ out.printf("getServletContextName=%s%n", getServletContext().getServletContextName());
+ out.printf("virtualServerName=%s%n", getServletContext().getVirtualServerName());
+ out.printf("contextPath=%s%n", getServletContext().getContextPath());
+ out.printf("version=%d.%d%n", getServletContext().getMajorVersion(), getServletContext().getMinorVersion());
+ out.printf("effectiveVersion=%d.%d%n", getServletContext().getEffectiveMajorVersion(), getServletContext().getEffectiveMinorVersion());
+ out.println("
");
+ out.println("Request Fields:
");
+ out.println("");
+ out.printf("remoteHost/Addr:port=%s/%s:%d%n", request.getRemoteHost(), request.getRemoteAddr(), request.getRemotePort());
+ out.printf("localName/Addr:port=%s/%s:%d%n", request.getLocalName(), request.getLocalAddr(), request.getLocalPort());
+ out.printf("scheme=%s method=%s protocol=%s%n", request.getScheme(), request.getMethod(), request.getProtocol());
+ out.printf("serverName:serverPort=%s:%d%n", request.getServerName(), request.getServerPort());
+ out.printf("requestURI=%s%n", request.getRequestURI());
+ out.printf("requestURL=%s%n", request.getRequestURL().toString());
+ out.printf("contextPath|servletPath|pathInfo=%s|%s|%s%n", request.getContextPath(), request.getServletPath(), request.getPathInfo());
+ out.printf("session/new=%s/%b%n", request.getSession(true).getId(), request.getSession().isNew());
+ out.println("
");
+ out.println("Request Headers:
");
+ out.println("");
+ for (String n : Collections.list(request.getHeaderNames())) {
+ for (String v : Collections.list(request.getHeaders(n))) {
+ out.printf("%s: %s%n", n, v);
+ }
+ }
+ out.println("
");
+ out.println("Response Fields:
");
+ out.println("");
+ out.printf("bufferSize=%d%n", response.getBufferSize());
+ out.printf("encodedURL(\"/foo/bar\")=%s%n", response.encodeURL("/foo/bar"));
+ out.printf("encodedRedirectURL(\"/foo/bar\")=%s%n", response.encodeRedirectURL("/foo/bar"));
+ out.println("
");
+ }
+}
diff --git a/managed_vms/async-rest/src/main/java/com/google/appengine/demos/asyncrest/AbstractRestServlet.java b/managed_vms/async-rest/src/main/java/com/google/appengine/demos/asyncrest/AbstractRestServlet.java
new file mode 100644
index 00000000000..07956c2dc3d
--- /dev/null
+++ b/managed_vms/async-rest/src/main/java/com/google/appengine/demos/asyncrest/AbstractRestServlet.java
@@ -0,0 +1,125 @@
+package com.google.appengine.demos.asyncrest;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.net.URLEncoder;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Queue;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * AbstractRestServlet.
+ *
+ */
+public class AbstractRestServlet extends HttpServlet {
+
+ protected final static int MAX_RESULTS = 5;
+
+ protected final static String STYLE = "";
+
+ protected final static String APPKEY = "com.google.appengine.demos.asyncrest.appKey";
+ protected final static String APPKEY_ENV = "PLACES_APPKEY";
+ protected final static String LOC_PARAM = "loc";
+ protected final static String ITEMS_PARAM = "items";
+ protected final static String LATITUDE_PARAM = "lat";
+ protected final static String LONGITUDE_PARAM = "long";
+ protected final static String RADIUS_PARAM = "radius";
+ protected String key;
+
+ @Override
+ public void init(ServletConfig servletConfig) throws ServletException {
+ //first try the servlet context init-param
+ String source = "InitParameter";
+ key = servletConfig.getInitParameter(APPKEY);
+ if (key == null || key.startsWith("${")) {
+ source = "System Property";
+ key = System.getProperty(APPKEY);
+ }
+ if (key == null || key.startsWith("${")) {
+ source = "Environment Variable";
+ key = System.getenv(APPKEY_ENV);
+ }
+ if (key == null) {
+ throw new UnavailableException("Places App Key not set");
+ }
+ if (key.startsWith("${")) {
+ throw new UnavailableException("Places App Key not expanded from " + source);
+ }
+ }
+
+ public static String sanitize(String s) {
+ if (s == null) {
+ return null;
+ }
+ return s.replace("<", "?").replace("&", "?").replace("\n", "?");
+ }
+
+ protected String restQuery(String coordinates, String radius, String item) {
+ try {
+ return "https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=" + key + "&location="
+ + URLEncoder.encode(coordinates, "UTF-8") + "&types=" + URLEncoder.encode(item, "UTF-8")
+ + "&radius=" + URLEncoder.encode(radius, "UTF-8");
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String generateResults(Queue