domingo, noviembre 21, 2010

Java - Google App Engine con Java


"Si usa algún código del siguiente tutorial, den el icono de ME GUSTA del Facebook que se encuentra en su mano derecha, para que se vuelva Seguidor del Blog y también comentenos que tal les pareció el tutorial"


1. Entorno


  • JDK 6 Update 21
  • Eclipse Helios
  • GWT y Google App Engine para Eclipse Helios (Google Update Site for Eclipse 3.6 - http://dl.google.com/eclipse/plugin/3.6)

2. Introducción



Google App Engine se permite ejecutar aplicaciones web en la infraestructura de Google. Las aplicaciones App Engine son fáciles de crear, mantener y actualizar al ir aumentando el tráfico y las necesidades de almacenamiento de datos. No se necesita utilizar ningún servidor: sólo se tiene que subir tu aplicación para que los usuarios puedan empezar a utilizarla.
La ventaja de App Engine es que hay una zona de pruebas que permite ejecutar las aplicaciones haciendo uso del lenguaje Java y Google App Engine y su principal ventaja es que las aplicaciones se ejecutan en un entorno seguro que proporciona acceso limitado al sistema operativo subyacente. Estas limitaciones permiten a App Engine distribuir solicitudes web de la aplicación en varios servidores e iniciar y detener los servidores según las demandas del tráfico. La zona de pruebas aísla la aplicación en su propio entorno seguro de confianza, totalmente independiente del hardware, el sistema operativo y la ubicación física del servidor web.

3. Conceptos Previos


3.1. Almacén de datos


App Engine proporciona un potente servicio de almacenamiento de datos distribuido que incluye un motor de
búsqueda y transacciones. A medida que el servidor web distribuido crece con el tráfico, el almacén de datos
distribuido crece con los datos. Las entidades del almacén de datos carecen de esquema. El código de aplicación se encarga de proporcionar y de respetar la estructura de las entidades de datos. Las interfaces JDO/JPA incluyen características para aplicar y respetar la estructura de la aplicación.

3.2. JPA


Java Persistence API, más conocida por su sigla JPA, es la API de persistencia desarrollada para la plataforma Java EE e incluida en el estándar EJB3. Esta API busca unificar la manera en que funcionan las utilidades que proveen un mapeo objeto-relacional. El objetivo que persigue el diseño de esta API es no perder las ventajas de la orientación a objetos al interactuar con una base de datos, como sí pasaba con EJB2, y permitir usar objetos regulares (conocidos como POJOs).

3.3. JDO


Objetos de datos Java (JDO) es una interfaz estándar para almacenar objetos que contienen datos en una base de datos. El estándar define interfaces para la anotación de objetos Java, la recuperación de objetos a través de consultas y la interacción con una base de datos a través de transacciones. Una aplicación que utiliza la interfaz JDO puede funcionar con diferentes tipos de bases de datos sin utilizar un código específico de bases de datos, incluidas bases de datos relacionales, bases de datos jerárquicas y bases de datos de objetos. Al igual que con otros estándares de interfaz, JDO permite que las aplicación migre fácilmente entre diferentes soluciones de almacenamiento.

4. Desarrollo


Lo que se piensa desarrollar es un ejemplo de registro de datos de un tutorial junto con su autor y mostrar la información de todos los tutoriales y de los tutoriales por autor. Para ejemplo se utilizara puros JSP, aunque también la parte de diseño lo podrían hacer usando GWT, como se explico en el Post anterior.

4.1. Crear el proyecto en Eclipse Helios

Debemos de crear un proyecto del tipo Aplicación Web para Google App Engine, es de la misma forma como se crea un proyecto para GWT. Para eso se debe de primero tener instalado GWT en Eclipse para que baje todas las librerías necesarias para Google App Engine.


















Como nombre al proyecto le vamos a poner "GAEConEclipseServlet" y dejamos activados el check box de GOOGLE APP ENGINE, y desactivamos el de GWT porque no lo vamos a usar para el ejemplo























Y nos crea una estructura de proyecto como la que se mostrara en la siguiente figura. La clase "GAEConEclipseServlet.java.java"  es el Servlet encargado de controlar las peticiones desde la parte Web. A través de peticiones del tipos POST y GET.




















4.2. Clase Tutorial

Crearemos una clase "Tutorial" que va a ser la clase encargado de manejar la persistencia de los datos. Esta clase tendrá las variables ID, autor, tutorial y fecha. Para eso hacemos clic derecho en el paquete "com.hwongu" y creamos la clase

















La clase "Tutorial" tendra el siguiente codigo:

package com.hwongu;

import java.util.Date;
import javax.jdo.annotations.*;

@PersistenceCapable (identityType=IdentityType.APPLICATION)
public class Tutorial {
 //Va a ser la clave primaria de la clase Tutorial
 @PrimaryKey
 //Para que genere el codigo de forma automatica
 @Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
 private Long id;
 //Creamos las variables persistence para insertar los datos
 @Persistent 
 private String autor;
 @Persistent 
 private String tutorial;
 @Persistent 
 private Date fecha;
 //Constructor de la clase
 public Tutorial(String autor, String tutorial){
  this.autor = autor;
  this.tutorial = tutorial;
  this.fecha = new Date();
 }
 //Metodos get y set
 public String getAutor() {
  return autor;
 }
 public void setAutor(String autor) {
  this.autor = autor;
 }
 public String getTutorial() {
  return tutorial;
 }
 public void setTutorial(String tutorial) {
  this.tutorial = tutorial;
 }
 public Date getFecha() {
  return fecha;
 }
 public void setFecha(Date fecha) {
  this.fecha = fecha;
 }
 public Long getId() {
  return id;
 }
 public void setId(Long id) {
  this.id = id;
 }
}

4.3. Clase PMF

De ahí debemos de crear una clase "PMF" que va a tener la variable encargada de controlar las peticiones de registros y búsqueda de la información almacenada.



















La clase tendrá el siguiente código fuente:

package com.hwongu;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

public final class PMF {
 //Variable encargada de controlar las peticiones
 private static final PersistenceManagerFactory instance =
   JDOHelper.getPersistenceManagerFactory("transactions-optional");
 //Para que no puedan instanciar la clase
 private PMF(){}
 //Retorna la instancia encargada de controlar las peticiones
 public static PersistenceManagerFactory get(){
    return instance;
 }
}

4.4. Clase TutorialesUtil

Después creamos una clase "TutorialesUtil" que va ser la clase que tendrá los métodos para registrar y hacer consulta de los datos, para hacer consulta de datos usando JDO se utiliza el lenguaje JDOQL, que es el query language para consultar datos persistentes.



















La clase tendrá el siguiente código:

package com.hwongu;

import java.util.List;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

public class TutorialUtil {
//Cuantos datos mostrara en la consulta
private final static int FETCH_MAX_RESULTS = 10;
//Metodo para insertar un dato
public static void insertar(String autorName, String tutorialName){
 //LLamamos a la clase que tendra la persistencia
 final PersistenceManager pm = PMF.get().getPersistenceManager();
 //Creamos nuestra variable del tipo tutorial
 final Tutorial tutorial = new Tutorial(autorName, tutorialName);
 //Y hacemos el dato que sea persistente
 pm.makePersistent(tutorial);
}
//Para consultar los tutoriales por autor
@SuppressWarnings("unchecked")
public static List<Tutorial> tutorialesPorAutor(String autor){
 final PersistenceManager pm = PMF.get().getPersistenceManager();
 String query = " select from " +
 Tutorial.class.getName() +
 " where autor == '" +
 autor + "'";
 List<Tutorial> tutorials = (List<Tutorial>)pm.newQuery(query).execute();
 return(tutorials);
}
//Para consulta todos los tutoriales
@SuppressWarnings("unchecked")
public static List<Tutorial> todosLosTutoriales(){
 final PersistenceManager pm = PMF.get().getPersistenceManager();
 final Query query = pm.newQuery(Tutorial.class);
 query.setRange(0, FETCH_MAX_RESULTS);
 return (List<Tutorial>) query.execute();
}

}

4.5. Clase GAEConEclipseServlet

Cuando ya terminamos de configurar nuestras clases tenemos que codificar el servlet que nos creo el eclipse ponemos lo siguiente (En el servlet "GAEConEclipseServlet")

package com.hwongu;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import javax.servlet.RequestDispatcher;

@SuppressWarnings("serial")
public class GAEConEclipseServlet extends HttpServlet {
    
 protected void processRequest(HttpServletRequest request, 
         HttpServletResponse response)
         throws ServletException, IOException {
 
  response.setContentType("text/html;charset=UTF-8");
  PrintWriter out = response.getWriter();
  try {
   if(request.getParameter("action").equals("create")){
     String autor = request.getParameter("autor");
     String tutorial = request.getParameter("tutorial");
     TutorialUtil.insertar(autor, tutorial);
     request.setAttribute("autor", autor);
     List<Tutorial> tutorials = TutorialUtil.tutorialesPorAutor(autor);
     request.setAttribute("tutorials", tutorials);
     RequestDispatcher rd =
         getServletContext().getRequestDispatcher("/tutorialShow.jsp");
     rd.forward(request, response);
   }else if(request.getParameter("action").equals("show")){
     List<Tutorial> tutorials = TutorialUtil.todosLosTutoriales();
     request.setAttribute("showFullTutorials", tutorials);
     RequestDispatcher rd =  
             getServletContext().getRequestDispatcher("/tutorialShowFull.jsp");
     rd.forward(request, response);
   }
  } finally { 
    out.close();
  }
 } 

 @Override
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
     processRequest(request, response);
 } 
 
 @Override
 protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
     processRequest(request, response);
 }
 
}

4.6. Paginas JSP

Y con eso terminamos de configurar nuestras clases que serán encargadas de registrar y buscar datos de los tutoriales y a la vez el controlador encargado de recibir las peticiones de las paginas JSP que vamos a crear. Las paginas jsp que crearemos serán los siguientes

index.jsp --> Que sera como un menú de opciones para realizar los procesos de registrar tutoriales y mostrar todos los tutoriales
tutorialCreate.jsp --> Pagina encargada para registrar los datos de los tutoriales
tutorialShow.jsp --> Muestra un tutorial por autor
tutorialShowFull.jsp --> Muestra todos los tutoriales

4.6.1. index.jsp


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Pagina de Inicio</title>
    </head>
    <body>
        <h1>Menu de Opciones</h1>
        <a href="/tutorialCreate.jsp">Crear Tutorial</a><br>
        <a href="/tutorial?action=show">Listar Tutorial</a>
    </body>
</html>

4.6.2. tutorialCreate.jsp


<%@page import="java.util.Date" %>
<%@page import="java.text.SimpleDateFormat" %>
<%
SimpleDateFormat sdf =("dd/MM/yyyy");String date = sdf.format(new Date());
%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>.:: Crear Tutorial::. </title>
 </head>
 <span>
  <a href="/tutorialCreate.jsp">Registrar Tutorial</a><br>
  <a href="/index.jsp">Ir al indice</a><br>
 </span>
 <span ><h1>Crear a Tutorial</h1></span>
  <form action="/tutorial" method="get">
  <table border="0">
   <tr>
       <td>Autor:</td>
       <td><input type="text" name="autor" /></td>
      </tr>
      <tr>
       <td>Tutorial:</td>
       <td><input type="text" name="tutorial" /></td>
      </tr>
      <tr>
       <td>Fecha:</td>
       <td><input readonly type="text" name="fecha" value="<%=date%>" /> </td>
      </tr>
      <tr>
       <td colspan="2" bgcolor="#ffffff" align="left">
       <input type="hidden" name="action" value="create"/>
       <input type="submit" value="Registrar" >
       </td>
      </tr>
   </table>
   </form>
 </body>
</html>

4.6.3. tutorialShow.jsp


<%@page import="com.hwongu.*" %>
<%@page import="java.util.*"%>
<%@page import="java.text.SimpleDateFormat" %>

<%
List<Tutorial> tutorials =("tutorials");
String autor =("autor");
SimpleDateFormat sdf = new SimpleDateFormat();
%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>.::Tutoriales por autor: <%=autor%> ::.</title>
 </head>
 <body>
  <span>
   <a href="/tutorialCreate.jsp">Registrar Tutorial</a><br>
   <a href="/index.jsp">Ir al indice</a>
  </span>
  <h1>Tutoriales del autor: <%=autor%></h1>
  <table border="1">
   <thead>
    <tr>
     <th>Id</th>
     <th>Tutorial</th>
     <th>Fecha</th>
    </tr>
   </thead>
  <tbody>
<%
 for (int idx = 0; idx < tutorials.size(); idx++) {
     Tutorial t = (Tutorial)tutorials.get(idx);
%>
   <tr>
    <td><%= t.getId() %></td>
    <td><%= t.getTutorial() %></td>
    <td><%= sdf.format(t.getFecha()) %></td>
   </tr>

<%}%>
  </tbody>
 </table>
 </body>
</html>

4.6.4. tutorialShowFull.jsp


<%@page import="com.hwongu.*" %>
<%@page import="java.util.*"%>
<%@page import="java.text.SimpleDateFormat" %>

<%
List<Tutorial> tutorials =("showFullTutorials");
SimpleDateFormat sdf = new SimpleDateFormat();
%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>.:: Todos los Tutoriales ::.</title>
 </head>
 <body>
  <span>
   <a href="/tutorialCreate.jsp">Registrar Tutorial</a><br>
   <a href="/index.jsp">Ir al indice</a>
  </span>
  <table border="1">
   <thead>
    <tr>
     <th>Id</th>
     <th>Autor</th>
     <th>Tutorial</th>
     <th>Fecha</th>
    </tr>
   </thead>
   <tbody>
<%
 for (int idx = 0; idx < tutorials.size(); idx++) {
     Tutorial t = (Tutorial)tutorials.get(idx);
%>
    <tr>
     <td><%= t.getId() %></td>
     <td><%= t.getAutor() %></td>
     <td><%= t.getTutorial() %></td>
     <td><%= sdf.format(t.getFecha()) %></td>
    </tr>

<%}%>
   </tbody>
  </table>
 </body>
</html>

4.6.5. Archivo web.xml


<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <servlet>
     <servlet-name>tutorial</servlet-name>
     <servlet-class>com.hwongu.GAEConEclipseServlet</servlet-class>
  </servlet>
  <servlet-mapping>
     <servlet-name>tutorial</servlet-name>
     <url-pattern>/tutorial</url-pattern>
  </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

5. Ejemplo de la Aplicación


Para ejecutar la aplicación debemos de hacerlo como debug para hacemos hacemos clic derecho en el proyecto, luego "Debug As" y de ahi seleccionamos "Web Application"























De ahí nos sale en la parte inferior la dirección electrónica que debemos de copiar y pegar en nuestro browser para ejecutar la aplicación










5.1. Menú de Opciones 


















5.2. Crear Tutorial














5.3. Tutoriales por Autor












5.4. Todos los Tutoriales

17 comentarios:

Este blog ha sido eliminado por un administrador de blog.

Henry muchas gracias por contestarme el Post anterior sobre el Google Web Toolkit. Aun tengo muchas dudas sobre el Google App Engine, podria contactarme contigo por medio de un correo electronico para que me saques de un par de dudas que tengo o te las escribo aqui. Me seria de mucha ayuda ya que no encuentro mucha documentacion al respecto. Que estes bien y muchas gracias.

Has tus consultas por el blog ... para que de esa forma todos puedan aprender. Saludos

1. Cuando creo un proyecto en Eclipse con Google App Engine y GWT activados me crea varios paquetes y varios archivos. Quisiera saber si esos paquetes y archivos son esenciales para el desarrollo de un proyecto o son un ejemplo.

2. Cual es la diferencia de crear un proyecto sin activar la casilla GWT y otro con las dos casillas.

quiero realizar una pequeña aplicacion en google app engine utilizando gwt, puede ser una suma pero no se por donde comenzar a tirar el codigo gracias

Jossimar

1. Si vas APP Engine con GWT para la presentación si debes de tener los paquetes que se crean

2. GWT sirve para crear lo que comúnmente se conoce como la capa de presentación, en lugar de usar GWT puedes usar JSP, JSF,etc

Juan

Trata de realizar el ejemplo que o propongo para q lo entiendas paso a paso

Este comentario ha sido eliminado por el autor.

Hola
buen tutorial, gracias me servido de mucho.
pero tengo unas dudas hacerca de como y donde se crean las clases jsp y html.

podrias emplicar un poco mas detallado una jsp y la html.

Este comentario ha sido eliminado por el autor.

La diferencia entre un JSP y HTML ... Que en un JSP puedes poner codigo Java para hacer tu pagina un poco dinamica, en cambio con HTML no lo puedes hacer. Saludos!!!

Gracias por tu Ejemplo; tengo un error al correrlo:

HTTP ERROR: 503
Problem accessing /. Reason:

SERVICE_UNAVAILABLE


--------------------------------------------------------------------------------
Powered by Jetty://

Espero que me buedas ayudar gracias

Hola livo

Ese es un error que no se inicio el servicio para ejecutar la aplicación. A veces cuando codificas y sale un error se queda pegado los datos de la sesión anterior y debes de reiniciar el servicio.

Buenas, quería hacerte una consulta cuando quiero crear una aplicacion con gwt 2.3, me devuelve un error que dice could not find main class, com.google.gwt.user.tools.WebAppCreator. Program will exit.Me permite crear un projecto en java, estoy usando el Eclipse Helios. Te agradecería enormemente q me orientes. Saludos!

Tienes que revisar que hayas bajado todas las librerías completas del GWT

Que buen tutorial amig apenas estoy iniciando y me gusto mucho me aclaro muchas dudas sobre esta tecnologia

Que buen tutorial amig apenas estoy iniciando y me gusto mucho me aclaro muchas dudas sobre esta tecnologia