Usa formularios con Java para el entorno de App Engine Standard

En esta parte del instructivo de Bookshelf para Java, se muestra cómo acceder a datos de formularios desde servlets.

Esta página forma parte de un instructivo de varias páginas. Para comenzar desde el principio y revisar las instrucciones de configuración, ve a la app de Bookshelf en Java.

Ejecuta la app en tu máquina local

Para ejecutar la app de manera local, haz lo siguiente:

  1. En el directorio getting-started-java/bookshelf-standard/2-structured-data, ingresa el siguiente comando para iniciar un servidor web local:

    mvn -Plocal clean appengine:devserver
  2. En tu navegador web, ve a http://localhost:8080.

Implementa la app en el entorno de App Engine Standard

Para implementar en el entorno de App Engine Standard, haz lo siguiente:

  1. Para crear un índice en Cloud Datastore que se suba a la app de Bookshelf, crea por lo menos un libro, y, luego, haz clic en Mis libros. Ten en cuenta que, si compilas la app con el comando clean, se borra ese índice local, por lo que debes hacerlo en la versión de la app que vas a implementar.
  2. En el directorio getting-started-java/bookshelf-standard/2-structured-data, ingresa el siguiente comando para implementar la app:
    mvn appengine:update -Dappengine.appId=[YOUR-PROJECT-ID] -Dappengine.version=[YOUR-VERSION]
    Reemplaza [YOUR-PROJECT-ID] por el ID del proyecto, y [YOUR-VERSION] por la versión, como 1, 2 o algún otro valor string que desees usar.
  3. En el navegador web, ingresa la siguiente dirección:
    https://[YOUR-PROJECT-ID].appspot.com
    Reemplaza [YOUR-PROJECT-ID] por el ID del proyecto.

Una vez que actualices la app, puedes volver a implementar la versión actualizada mediante el mismo comando que usaste cuando la implementaste por primera vez. Para ello, especifica el mismo ID del proyecto y la misma versión. Esto reemplazará la app implementada actualmente. Si especificas una string de versión diferente en la línea de comandos actualizada, la implementación nueva crea una versión nueva de la app y la convierte a la versión actualmente en uso.

Borra las versiones de la app que no estén en uso para reducir costos.

Para borrar una versión de una app, haz lo siguiente:

  1. In the GCP Console, go to the Versions page for App Engine.

    Go to the Versions page

  2. Select the checkbox for the non-default app version you want to delete.
  3. Click Delete to delete the app version.

Para obtener toda la información acerca de la limpieza de los recursos facturables, consulta la sección Limpieza en el paso final de este instructivo.

Controla los envíos de los usuarios con formularios

El formulario te permite agregar y editar envíos de libros en la app.

Imagen de un formulario para agregar y editar

Cuando el navegador solicita /create, el servlet de Google Kubernetes Engine carga CreateBookServlet y llama al método doGet. Luego, la solicitud se reenvía al servlet /base.jsp, que incluye el servlet /form.jsp. Después de que envías el formulario, se llama al método doPost de CreateBookServlet.

En CreateBookServlet.java, el método doGet procesa la solicitud de un formulario y configura los atributos que usará el archivo JSP:

@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
    IOException {
  req.setAttribute("action", "Add");          // Part of the Header in form.jsp
  req.setAttribute("destination", "create");  // The urlPattern to invoke (this Servlet)
  req.setAttribute("page", "form");           // Tells base.jsp to include form.jsp
  req.getRequestDispatcher("/base.jsp").forward(req, resp);
}

El archivo base.jsp sirve de base para las páginas HTML de la app. Comienza con la incorporación de la biblioteca de etiquetas estándar de JSP. Las etiquetas principales de JSTL se identifican por su inicio con <c: y proporcionan variables, control de flujo, administración de URL y compatibilidad miscelánea. Las funciones de JSTL se identifican mediante etiquetas que comienzan con <fn: y proporcionan colecciones y bibliotecas de manipulación de strings. A continuación, se muestra un resumen de las etiquetas de JSTL que usa la app de Bookshelf:

Etiqueta JSTL Descripción
<c:if ... Evalúa la expresión test; incluye contenido si es “true”.
<c:choose> Etiqueta condicional que establece el contexto para c:when y c:otherwise.
<c:when ... Incluye contenido si test es “true”.
<c:otherwise> Si c:when no es “true”, incluye este contenido.
<c:import url="" /> Incluye los contenidos de la url dentro de la página.
<c:out value="" /> Evalúa la expresión para value y muestra una versión codificada.
${fn:escapeXml()} Caracteres especiales de escape para páginas web.


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<html lang="en">
  <head>
    <title>Bookshelf - Java on Google Cloud Platform</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
  </head>
  <body>
    <div class="navbar navbar-default">
      <div class="container">
        <div class="navbar-header">
          <div class="navbar-brand">Bookshelf</div>
        </div>
        <ul class="nav navbar-nav">
          <li><a href="/">Books</a></li>
          <c:if test="${isAuthConfigured}"><li><a href="/books/mine">My Books</a></li></c:if>
        </ul>
        <p class="navbar-text navbar-right">
          <c:choose>
          <c:when test="${not empty token}">
          <!-- using pageContext requires jsp-api artifact in pom.xml -->
          <a href="/logout">
            <c:if test="${not empty userImageUrl}">
              <img class="img-circle" src="${fn:escapeXml(userImageUrl)}" width="24">
            </c:if>
            ${fn:escapeXml(userEmail)}
          </a>
          </c:when>
          <c:when test="${isAuthConfigured}">
          <a href="/login">Login</a>
          </c:when>
          </c:choose>
        </p>
      </div>
    </div>
    <c:import url="/${page}.jsp" />
  </body>
</html>

El formulario HTML se crea con JavaServer Pages, que es similar a un motor de plantillas de Java, pero se ejecuta como servlet. En el siguiente código de JSP se especifica que el formulario incluye campos de entrada de texto para el título, el autor, la fecha de publicación, la descripción, la imagen de portada y un botón “Guardar”:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<div class="container">
  <h3>
    <c:out value="${action}" /> book
  </h3>

  <form method="POST" action="${destination}">

    <div class="form-group">
      <label for="title">Title</label>
      <input type="text" name="title" id="title" value="${fn:escapeXml(book.title)}" class="form-control" />
    </div>

    <div class="form-group">
      <label for="author">Author</label>
      <input type="text" name="author" id="author" value="${fn:escapeXml(book.author)}" class="form-control" />
    </div>

    <div class="form-group">
      <label for="publishedDate">Date Published</label>
      <input type="text" name="publishedDate" id="publishedDate" value="${fn:escapeXml(book.publishedDate)}" class="form-control" />
    </div>

    <div class="form-group">
      <label for="description">Description</label>
      <textarea name="description" id="description" class="form-control">${fn:escapeXml(book.description)}</textarea>
    </div>

    <div class="form-group ${isCloudStorageConfigured ? '' : 'hidden'}">
      <label for="image">Cover Image</label>
      <input type="file" name="file" id="file" class="form-control" />
    </div>

    <div class="form-group hidden">
      <label for="imageUrl">Cover Image URL</label>
      <input type="hidden" name="id" value="${book.id}" />
      <input type="text" name="imageUrl" id="imageUrl" value="${fn:escapeXml(book.imageUrl)}" class="form-control" />
    </div>

    <button type="submit" class="btn btn-success">Save</button>
  </form>
</div>

Envía el formulario

El método doPost crea un objeto Book a partir de la lectura de los parámetros del formulario a través de las llamadas a req.getParameter() y proporciona el objeto Book a un objeto BookDao nuevo que agrega la entidad de libro nueva a Cloud Datastore. Después de guardar el libro en Cloud Datastore, la página se redirecciona a /read, para que puedas ver lo que acabas de guardar. El acceso a la sesión y la creación de libros se analizarán más adelante:

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
    IOException {
  Book book = new Book.Builder()
      .author(req.getParameter("author"))   // form parameter
      .description(req.getParameter("description"))
      .publishedDate(req.getParameter("publishedDate"))
      .title(req.getParameter("title"))
      .imageUrl(null)
      .build();

  BookDao dao = (BookDao) this.getServletContext().getAttribute("dao");
  try {
    Long id = dao.createBook(book);
    resp.sendRedirect("/read?id=" + id.toString());   // read what we just wrote
  } catch (Exception e) {
    throw new ServletException("Error creating book", e);
  }
}
¿Te ha resultado útil esta página? Enviar comentarios: