Você está na página 1de 21

Cloud Computing

Google AppEngine: Caractersticas


Ofrece una plataforma completa para el alojamiento y escalado automtico de aplicaciones,
consistiendo en:
Servidores de aplicaciones Python y Java
La base de datos BigTable
El sistema de ficheros GFS
Como desarrollador simplemente tienes que subir tu cdigo Python o Java compilado a Google,
lanzar la aplicacin y monitorizar el uso y otras mtricas
Google AppEngine incluye la librera estndar de Python 2.5 y soporta Java 1.6
No todas las acciones se permiten (acceso a ficheros, llamadas al SO, algunas llamadas de red)
Se ejecuta en un entorno restringido para permitir que las aplicaciones escalen
Ejemplo:
https://appengine.google.com
http://enpresadigitala.appspot.com/encuestas
http://code.google.com/intl/en/appengine/docs/
9. Google AppEngine: Python y Java
Vamos a revisar primero (brevemente) cmo realizar aplicaciones con Python
Luego nos centraremos en cmo hacerlo desde Java en mayor grado de detalle

11. Principios
Una aplicacin de AppEngine se comunica con el servidor que la aloja a travs de CGI
Cuando recibe una peticin el servidor lee de la entrada estndar y de las variables de
entorno
Cuando genera una respuesta escribe a la salida estndar

12. Mi primera aplicacin
Crear el directorio helloworld
Crea el fichero helloworld.py dentro de l con el siguiente contenido, que corresponde
a una respuesta HTTP:
print 'Content-Type: text/plain'
print ''
print 'Hello, world!
Crea el fichero de configuracin requerido por toda aplicacin AppEngine denominado
app.yaml, en formato YAML (http://www.yaml.org/):
http://code.google.com/appengine/docs/configuringanapp.html
application: helloworld
version: 1
runtime: python
api_version: 1
handlers:
- url: /.*
script: helloworld.py
Arranca el servidor con el comando:dev_appserver.py helloworld/

El switch--help da ms indicaciones sobre las opciones aceptadas por el servidor
Vete a la siguiente URL para probarlo: http://localhost:8080/

13. Ejecutando Hola Mundo en Google App Engine

14. Opciones Avanzadas para GAE forPython
Framework webapp que soporta el estndar WSGI
Acceso a datos de usuarios mediante la Users API
DataStore API
Plantillas en Google AppEngine

15. Usando el Almacn de Datos de Google AppEngine
Guardar datos en una aplicacin web escalable puede ser difcil
La infraestructura de AppEngine se encarga de la distribucin, replicacin y balanceo
de carga de los datos detrs de una API sencilla que tambin ofrece un motor de
consultas y transacciones
App Engine incluye una API de modelado de datos para Python
Se asemeja a la API de Django pero utiliza el servidor de datos escalable BigTable por
detrs.
No esrelacional, todaslasentidades de un mismotipotienenlasmismaspropiedades
Unapropiedadpuedeteneruno o variosvalores
El siguiente import nos da acceso a la base de datos de Google AppEngine:
fromgoogle.appengine.extimportdb
Para ms detalles sobre el DataStore API ir a:
http://code.google.com/appengine/docs/datastore/

16. La API del DataStore
Incluye una API de modelado de datos y un lenguaje similar a SQL que NO permite
JOINs y que se llama GQL, haciendo el desarrollo de aplicaciones escalables basadas en
datos muy sencillo.
fromgoogle.appengine.extimportdbfromgoogle.appengine.apiimportusersclassPet(db.
Model): name = db.StringProperty(required=True) type =
db.StringProperty(required=True, choices=set(["cat", "dog", "bird"])) birthdate =
db.DateProperty() weight_in_pounds = db.IntegerProperty() spayed_or_neutered =
db.BooleanProperty() owner = db.UserProperty()pet =
Pet(name="Fluffy", type="cat", owner=users.get_current_user())pet.weight_
in_pounds = 24pet.put()

17. GQL Query Language
Para limpiar la base de datos creada: dev_appserver.py --clear_datastorehelloworld/
Ejemplo GQL:
ifusers.get_current_user():
user_pets = db.GqlQuery("SELECT * FROM Pet WHERE pet.owner = :1,
users.get_current_user())
forpet in user_pets:
pet.spayed_or_neutered = True
db.put(user_pets)



24. Subiendo la aplicacin
Es necesario realizar los siguientes pasos:
Editar el fichero app.yaml file y cambiar el valor de la aplicacin: de helloworld al
nombre de id de aplicacin (enpresadigitala)
Ejecutar el siguiente comando: appcfg.py updatehelloworld/
Acceder a la aplicacin en http://application-id.appspot.com, por ejemplo en
http://enpresadigitala.appspot.com/


App Engine para Java
Crea aplicaciones web a travs de tecnologas estndar de Java y las ejecuta en la
infraestructura escalable Google
Usa JVM Java 6, interfaz de servlets Java y la compatibilidad de interfaces
estndar como JDO, JPA, JavaMail y JCache
AppEngine utiliza el estndar Java Servlet para aplicaciones web
JVM se ejecuta en un entorno seguro de la "zona de pruebas" para aislar tu aplicacin
por servicio y seguridad.
Una aplicacin en GAE slo pueda realizar acciones que no interfieran con el
rendimiento ni con la escalabilidad de otras aplicaciones.

30. Funcionalidad de AppEnginefor Java
AppEngine proporciona un conjunto de servicios escalables que pueden utilizar las
aplicaciones para:
Almacenar datos persistentes. En Java, el almacn de datos admite 2 interfaces Java
estndar: los objetos de datos Java (JDO) 2.3 y el API de persistencia de Java (JPA) 1.0.
Acceder a recursos en la red. A travs de la URL Fectch API.
Cachear informacin. Memcache de AppEngine proporciona un almacenamiento en
cach distribuido, transitorio y rpido de los resultados de clculos y consultas de
almacn de datos. La interfaz Java implementa JCache (JSR 107).
Enviar email. Da soporte de JavaMail para el envo de correos
Procesar imgenes. A travs de la Images Java API, permite a las aplicaciones
transformar y manipular datos de imgenes en varios formatos.
Gestionar usuarios. A travs de la Users Java API permite utilizar Cuentas de
Google para la autenticacin del usuario.
Lanzar tareas planificadas o en background. Mediante la TaskQueue Java API y la
gestin de tareas por Cron.

31. Instalacin de AppEnginefor Java
Descargar el fichero de:
http://code.google.com/intl/es/appengine/downloads.html#Google_App_Engine_SDK
_for_Java
Descomprimir el fichero .zip
Crear una variable de entorno APPENGINE_JAVA_SDK que apunte al directorio raz de
instalacin de la SDK
Incluir el directorio %APPENGINE_JAVA_SDK%binen la variable de entorno PATH

32. Pasos para crear una Aplicacin con Google AppEngine para Java
Crear el proyecto de la aplicacin
Crear la clase servlet
Crear el fichero de despliegue de la aplicacin: web.xml
Crear el archivo appengine-web.xml
Ejecutar el proyecto
Probar el proyecto: http://localhost:8080/<nombre-aplicacin>
Subir la aplicacin al dominio appspot.com

33. Configuracin del Entorno
Instalar java
Descomprimir la distribucin de GAE for Java a una carpeta de tu disco duro
Modificar la variable de entorno APPENGINE_JAVA_SDK para que apunte a ese
directorio
Modificar la variable de entorno PATH para que apunte a
%APPENGINE_JAVA_SDK%bin
Descomprimir el fichero downloadsapache-ant-1.8.1-bin.zip
Modificar la variable de entorno PATH para que apunte a <ANT_DIR>bin
cdexamplesgoogleappenginejavaguestbook
ant

34. Paso 1: Creando la estructura del proyecto
Dos opciones:
Usar el plug-in para Eclipse:
http://code.google.com/intl/es/appengine/docs/java/tools/eclipse.html
Usar la plantilla de proyecto disponible en
%APP_ENGINE_HOME%demosnew_project_template
Las aplicaciones Java de AppEngine utilizan el API Java Servlet para interactuar con el
servidor web.
Un servlet HTTP es una clase de aplicacin que puede procesar y responder solicitudes
web. Esta clase ampla la clase javax.servlet.GenericServlet o a la
clase javax.servlet.http.HttpServlet.
La estructura del directorio de trabajo ser la siguiente:
Guestbook/
src/
...Java sourcecode...
META-INF/
...otherconfiguration...
war/
...JSPs, images, data files...
WEB-INF/
...appconfiguration...
classes/
...compiledclasses...
lib/
...JARsforlibraries...

35. Paso 2: Creando la clase Servlet
Crear en el directorio src/guestbook/ un fichero
denominado GuestbookServlet.java con el siguiente contenido:
packageguestbook;importjava.io.IOException;importjavax.servlet.http.*;publicclassGu
estbookServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,
HttpServletResponseresp) throwsIOException
{ resp.setContentType("text/plain"); resp.getWriter().println("Hello, world"); }}

36. Paso 3: Creando el fichero de despliegue web.xml
Cuando el servidor web recibe una solicitud, decide qu clase de servlet ejecutar
mediante un archivo de configuracin conocido como "descriptor de implementacin
de la aplicacin web".
Este archivo se denomina web.xml y se ubica en el directorio war/WEB-INF/ del
directorio que contiene los ficheros de una aplicacin web en Java
<?xmlversion="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-appxmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
<servlet>
<servlet-name>guestbook</servlet-name>
<servlet-class>guestbook.GuestbookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>guestbook</servlet-name>
<url-pattern>/guestbook</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>

37. Paso 4: Crear el fichero de configuracin de aplicacin GAE: appengine-web.xml
AppEngine necesita un archivo de configuracin adicional para poder desarrollar y
ejecutar la aplicacin, denominado appengine-web.xml
Se ubica en WEB-INF/ junto a web.xml.
Incluye la ID registrada de la aplicacin, el nmero de versin de la aplicacin y listas
de archivos que se deben tratar como archivos estticos (por ejemplo, imgenes y CSS)
y archivos de recursos (por ejemplo, JSP y otros datos de aplicacin).
El directorio war/WEB-INF/ incluye un archivo denominado appengine-web.xml que
contiene lo siguiente:
<?xmlversion="1.0" encoding="utf-8"?>
<appengine-web-appxmlns="http://appengine.google.com/ns/1.0">
<application>librocitas</application>
<version>1</version>
</appengine-web-app>

38. Paso 5: Ejecucin del Proyecto
El SDK de AppEngine incluye un servidor web de pruebas para depurar tu aplicacin.
El servidor simula los servicios y el entorno AppEngine, que incluyen restricciones en la
zona de pruebas, el almacn de datos y los servicios.
Con el fichero ant ejecuta: antrunserver
Puedes detenerlo con Ctrl-C

39. Paso 6: Subiendo la aplicacin
Puedes crear y administrar aplicaciones web AppEngine con la consola de
administracin de AppEngine a travs de la siguiente URL:
http://appengine.google.com/
Para crear una nueva aplicacin, haz clic en el botn "CreateanApplication" (Crear
aplicacin)
Edita el archivo appengine-web.xml y, a continuacin, cambia el valor del
elemento <application> para que sea la ID registrada de tu aplicacin (librocitas).
Ejecuta el siguiente comando en lnea de comandos para subir la aplicacin: $ appcfg
update www
Vete a: http://librocitas.appspot.com/

40. El fichero de Ant
Apache Ant facilita la administracin de tu proyecto desde la lnea de comandos o
desde otros entornos de desarrollo integrados (IDE) compatibles con Ant.
El SDK de Java incluye un conjunto de macros de Ant para realizar tareas de desarrollo
de AppEngine, entre las que se incluyen:
El inicio del servidor de desarrollo y
La subida de la aplicacin a AppEngine
Algunos problemas con el build.xml suministrado por new-project-template
Fichero adaptado en examples/guestbook/build.xml:
Hay que definir variable de entorno APP_ENGINE_SDK para desligar build.xml de su
localizacin en disco
Introducir tarea para copiar jars con dependencias

41. Usando el Servicio de Usuarios
Google AppEngine ofrece varios servicios tiles basados en la infraestructura de
Google a los que se puede acceder a travs de aplicaciones utilizando una serie de
bibliotecas incluidas en el kit de desarrollo de software (SDK)
Por ejemplo, el servicio de usuarios te permite integrar tu aplicacin con cuentas de
usuarios de Google
packageguestbook;importjava.io.IOException;importjavax.servlet.http.*;importcom.go
ogle.appengine.api.users.User;importcom.google.appengine.api.users.UserService;imp
ortcom.google.appengine.api.users.UserServiceFactory;publicclassGuestbookServletex
tendsHttpServlet { publicvoiddoGet(HttpServletRequestreq,
HttpServletResponseresp) throwsIOException { UserServiceuserService =
UserServiceFactory.getUserService(); Useruser =
userService.getCurrentUser(); if (user != null)
{ resp.setContentType("text/plain"); resp.getWriter().println("Hello, " +
user.getNickname()); } else
{ resp.sendRedirect(userService.createLoginURL(req.getRequestURI())); } }}

Uso de un JSP
Aunque podramos generar el cdigo HTML para la interfaz de usuario directamente a
partir del cdigo Java del servlet, no sera algo fcil de mantener, ya que el cdigo
HTML se complica
Es ms conveniente utilizar un sistema de plantillas, en el que la interfaz de usuario
est diseada e implementada en archivos independientes con marcadores y lgica
para insertar datos proporcionados por la aplicacin.
Pasos:
En el directorio war/, crea un archivo llamado guestbook.jsp con el contenido de la
siguiente transparencia
Modificar el fichero web.xml para que el welcome-file apunte a guestbook.jsp
Acceder a la ruta: http://localhost:8080/guestbook.jsp o http://localhost:8080/
Al cargar una JSP por primera vez, el servidor de desarrollo lo convierte en cdigo
fuente Java y, a continuacin, compila este cdigo en cdigo de bytes de Java
Al subir la aplicacin a AppEngine, el SDK compila todas las JSP en cdigo de bytes y
nicamente sube el cdigo de bytes.

43. Uso de un JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.google.appengine.api.users.User" %>
<%@ page import="com.google.appengine.api.users.UserService" %>
<%@ page import="com.google.appengine.api.users.UserServiceFactory" %>
<html>
<body><%
UserServiceuserService = UserServiceFactory.getUserService();
Useruser = userService.getCurrentUser();
if (user != null) {%>
<p>Hello, <%= user.getNickname() %>! (You can<a href="<%=
userService.createLogoutURL(request.getRequestURI()) %>">signout</a>.)</p><%
} else {%>
<p>Hello!<a href="<%= userService.createLoginURL(request.getRequestURI())
%>">Sign in</a>toincludeyournamewithgreetingsyou post.</p><%
}%>
</body>

44. Formulario Libro Invitados
La aplicacin de libro de invitados necesita un formulario web para que el usuario
publique un nuevo saludo, as como una forma de procesar ese formulario
El cdigo HTML del formulario se inserta en la JSP guestbook.jsp:
<form action="/sign" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Post Greeting" /></div>
</form>
El destino del formulario es una nueva URL, /sign, controlada por una nueva clase de
servlet,SignGuestbookServlet que procesa el formulario y redirige a: /guestbook.jsp
Es necesario modificar web.xml para crear una nueva entrada para este servlet, con los
siguientes datos:
<servlet>
<servlet-name>sign</servlet-name>
<servlet-class>guestbook.SignGuestbookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sign</servlet-name>
<url-pattern>/sign</url-pattern>
</servlet-mapping>

45. El Servlet que Procesa una Nueva Entrada en Libro
packageguestbook;
importjava.io.IOException;
importjava.util.logging.Logger;
importjavax.servlet.http.*;
importcom.google.appengine.api.users.User;
importcom.google.appengine.api.users.UserService;
importcom.google.appengine.api.users.UserServiceFactory;
publicclassSignGuestbookServletextendsHttpServlet {
privatestatic final Logger log =
Logger.getLogger(SignGuestbookServlet.class.getName());
publicvoiddoPost(HttpServletRequestreq, HttpServletResponseresp)
throwsIOException{
UserServiceuserService = UserServiceFactory.getUserService();
Useruser = userService.getCurrentUser();
Stringcontent = req.getParameter("content");
if (content == null) {
content = "(No greeting)";
}
if (user != null) {
log.info("Greetingpostedbyuser " + user.getNickname() + ": " + content);
} else {
log.info("Greetingpostedanonymously: " + content);
}
resp.sendRedirect("guestbook.jsp");
}
}

46. Logeo de Informacin con AppEngine
El nuevo servlet utiliza la clase java.util.logging.Logger para escribir mensajes en el
registro.
Puedes controlar el comportamiento de esta clase a travs de un
archivo logging.properties y de un conjunto de propiedades del sistema en el
archivo appengine-web.xml de la aplicacin.
Copia el archivo de ejemplo del SDK appengine-java-
sdk/config/user/logging.properties en el directorio war/WEB-INF/ de la aplicacin
Para modificar el nivel de registro de todas las clases del paquete guestbook, edita el
archivo logging.properties y aade una entrada para guestbook.level, como se muestra
a continuacin:
.level = WARNING
guestbook.level = INFO
A continuacin edita el archivo war/WEB-INF/appengine-web.xml de la aplicacin
como se indica:
<appengine-web-appxmlns="http://appengine.google.com/ns/1.0"> ...
<system-properties>
<propertyname="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
</appengine-web-app>
Los ficheros de logeo se descargan con la consola de administracin o la aplicacin
appcfg de AppEngine: https://appengine.google.com/logs

47. Uso del Almacen de Datos JDO
La infraestructura de AppEngine se encarga de todas las tareas de distribucin,
replicacin y balanceo de carga de los datos de un API sencilla, adems de ofrecer un
potente motor de consulta y transacciones.
Ofrece dos API: un API estndar y otra de nivel inferior.
AppEnginefor Java permite el uso de dos estndares de API diferentes para el almacn
de datos: Objetos de datos Java (JDO) y API de persistencia Java (JPA).
Estas interfaces las proporciona DataNucleus Access Platform, una implementacin de
software libre de varios estndares de persistencia Java, con un adaptador para Google
DataStore
Utilizaremos la interfaz JDO para la recuperacin y la publicacin de los mensajes de
los usuarios en el almacn de datos de AppEngine.
Access Platformnecesita un archivo de configuracin que le indique que debe utilizar el
almacn de datos de AppEngine como servidor para la implementacin de JDO: META-
INF/jdoconfig.xml
Documentacin detallada de JDO puede encontrarse en:
http://code.google.com/appengine/docs/java/datastore/

48. Funcionamiento de JDO
Al crear clases JDO, debes utilizar anotaciones Java para describir cmo se deben
guardar las instancias en el almacn de datos y cmo se deben volver a crear al
recuperarlas de dicho almacn.
Access Platform conecta las clases de datos a la implementacin mediante un paso de
procesamiento posterior a la compilacin, que DataNucleus denomina "mejora" de las
clases.
JDO permite almacenar objetos Java (a veces denominados "objetos Java antiguos y
simples" o POJO) en cualquier almacn de datos con un adaptador compatible con
JDO, como DataNucleus Access Platform
El complemento Access Platform para el almacn de datos de AppEngine permite
almacenar instancias de clases definidas en el almacn de datos de AppEngine
Ejemplo: la clase Greeting representar mensajes individuales publicados en el libro de
invitados de nuestra aplicacin

49. La Clase de Persistencia Greeting
packageguestbook;
importjava.util.Date;
importjavax.jdo.annotations.IdGeneratorStrategy;
importjavax.jdo.annotations.IdentityType;
importjavax.jdo.annotations.PersistenceCapable;
importjavax.jdo.annotations.Persistent;
importjavax.jdo.annotations.PrimaryKey;
importcom.google.appengine.api.users.User;
@PersistenceCapable(identityType = IdentityType.APPLICATION)
publicclassGreeting {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
@Persistent
privateUserauthor;
@Persistent
privateStringcontent;
@Persistent
private Date date;
publicGreeting(Userauthor, Stringcontent, Date date) {
this.author = author;
this.content = content;
this.date = date;
}
...
}

50. La Clase de Persistencia Greeting
Esta sencilla clase define tres propiedades para un saludo: author, content y date
Estos tres campos privados presentan la anotacin @Persistent, que indica a
DataNucleus que debe almacenarlos como propiedades de objetos en el almacn de
datos de AppEngine.
La clase tambin define un campo llamado id, una clave Long que presenta dos
anotaciones: @Persistent y @PrimaryKey.
El almacn de datos de AppEngine tiene una nocin de las claves de entidades y puede
representar las claves de varias formas en un objeto.
Ms informacin sobre cmo definir modelos de datos puede encontrarse en:
http://code.google.com/intl/es/appengine/docs/java/datastore/dataclasses.html

51. Serializando datos con JDO
Cada solicitud que utiliza el almacn de datos crea una nueva instancia de la clase
PersistenceManager que se obtiene a travs de PersistenceManagerFactory
Una instancia de PersistenceManagerFactory tarda algn tiempo en inicializarse
Afortunadamente, slo se necesita una instancia para cada aplicacin
Creamos la clase singletonPMF para resolverlo:
packageguestbook;
importjavax.jdo.JDOHelper;
importjavax.jdo.PersistenceManagerFactory;
public final class PMF {
privatestatic final PersistenceManagerFactorypmfInstance =
JDOHelper.getPersistenceManagerFactory("transactions-optional");
private PMF() {}
publicstaticPersistenceManagerFactoryget() { returnpmfInstance;
}
}
Para usarlo creamos una nueva instancia de Greeting mediante la ejecucin del
constructor.
Para guardar la instancia en el almacn de datos, crea una clase PersistenceManager a
travs de PMF.get() e invocamos sobre l makePersistent()

52. Serializando datos con JDO
Dentro del fichero SignGuestBookServlet introduciramos los siguientes cambios para
serializar los saludos en AppEngineDataStore, a travs de JDO:
Stringcontent = req.getParameter("content");
Date date = new Date();
Greetinggreeting = new Greeting(user, content, date);
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
pm.makePersistent(greeting);
} finally {
pm.close();
}

53. Consultando datos con JDO
El estndar JDO define un mecanismo para consultas de objetos persistentes
denominado JDOQL.
Modificaremos guestbook.jsp para realizar la consulta introduciendo los siguientes
cambios:
<%@ page import="java.util.List" %><%@ page
import="javax.jdo.PersistenceManager" %><%@ page import="guestbook.Greeting"
%><%@ page import="guestbook.PMF" %>

<%
PersistenceManager pm = PMF.get().getPersistenceManager();
String query = "select from " + Greeting.class.getName() + " order by date desc range
0,5";
List<Greeting> greetings = (List<Greeting>) pm.newQuery(query).execute();
if (greetings.isEmpty()) { %>
<p>Theguestbook has no messages.</p> <%
} else {
for (Greeting g : greetings) {
if (g.getAuthor() == null) { %>
<p>Ananonymouspersonwrote:</p> <%
} else { %>
<p><b><%= g.getAuthor().getNickname() %></b> wrote:</p> <%
} %>
<blockquote><%= g.getContent() %></blockquote> <%
}
}
pm.close();
%>

54. Usando Ficheros Estticos
Hay muchos casos en los que querrs mostrar los archivos estticos directamente en el
navegador web: imgenes, vdeos
Para una mayor eficiencia, AppEngine muestra los archivos estticos desde servidores
independientes en lugar de los que ejecutan servlets.
AppEngine considera todos los archivos del directorio WAR como archivos estticos,
salvo JSP y los archivos de WEB-INF/
Cualquier solicitud de una URL cuya ruta coincida con un archivo esttico lo muestra
Puedes configurar los archivos que quieres que AppEngine considere como archivos
estticos a travs del archivo appengine-web.xml
La siguiente pgina da ms informacin al respecto:
http://code.google.com/intl/es/appengine/docs/java/config/appconfig.html
Para este ejemplo:
Crear main.css con el siguiente contenido:
body { font-family: Verdana, Helvetica, sans-serif; background-color: #FFFFCC; }
Aadir a guestbook.jsp lo siguiente:
<head> <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> </head>

55. Creando de Objetos y Claves
Para almacenar un objeto de datos sencillo en el almacn de datos, ejecuta el
mtodo makePersistent() del PersistenceManager y transfirelo a la instancia.
PersistenceManager pm = PMF.get().getPersistenceManager();
Employee e = new Employee("Alfred", "Smith", new Date());
try {
pm.makePersistent(e);
} finally {
pm.close();
}
Las claves ms sencillas estn basadas en los tipos Long o String, pero tambin se
pueden crear con la clase Key.
importcom.google.appengine.api.datastore.Key;
importcom.google.appengine.api.datastore.KeyFactory;
// ...
Key k = KeyFactory.createKey(Employee.class.getSimpleName(),
"Alfred.Smith@example.com");
Para recuperar un elemento por clave podemos usar lo siguiente, se puede pasar como
segundo argumento una clave, un entero o un string:
Employee e = pm.getObjectById(Employee.class, "Alfred.Smith@example.com");

56. Actualizacin y Borrado de Objetos
El siguiente cdigo muestra cmo actualizar un objeto persistente:
publicvoidupdateEmployeeTitle(Useruser, StringnewTitle) {
PersistenceManager pm = PMF.get().getPersistenceManager(); try { Employee e =
pm.getObjectById(Employee.class, user.getEmail()); if (titleChangeIsAuthorized(e,
newTitle) { e.setTitle(newTitle); } else { throw new
UnauthorizedTitleChangeException(e, newTitle); } } finally { pm.close(); }
}
El siguiente ejemplo muestra cmo borrar un objeto:
pm.deletePersistent(e);

57. Realizando Consultas con JDO
JDOQL es similar a SQL, aunque es ms adecuado para bases de datos relacionadas con
objetos, como, por ejemplo, el almacn de datos de AppEngine.
Dos usos diferentes:
Puedes especificar parte o la totalidad de la consulta mediante mtodos de ejecucin
en el objeto de consulta
importjava.util.List;
importjavax.jdo.Query;
// ...
Queryquery = pm.newQuery(Employee.class);
query.setFilter("lastName == lastNameParam");
query.setOrdering("hireDatedesc");
query.declareParameters("StringlastNameParam");
try {
List<Employee> results = (List<Employee>) query.execute("Smith");
if (results.iterator().hasNext()) {
for (Employee e : results) {
// ...
}
} else {
// ... no results ...
}
} finally {
query.closeAll();
}

58. Realizando Consultas con JDO
Puedes especificar una consulta completa en una cadena mediante la sintaxis de
cadena JDOQL:
Queryquery = pm.newQuery("selectfromEmployee " + "wherelastName ==
lastNameParam " + "orderbyhireDatedesc " + "parametersStringlastNameParam");
List<Employee> results = (List<Employee>) query.execute("Smith");
Otro modo:
Queryquery = pm.newQuery(Employee.class, "lastName ==
lastNameParamorderbyhireDatedesc");
query.declareParameters("StringlastNameParam");
List<Employee> results = (List<Employee>) query.execute("Smith");
Query query = pm.newQuery(Employee.class, "lastName == 'Smith' order by
hireDatedesc");

59. Filtros y Restricciones en Consultas JDO sobre AppEngine
Algunos ejemplos de filtros son:
query.setFilter("lastName == 'Smith' && hireDate > hireDateMinimum");
query.declareParameters("Date hireDateMinimum");
Queryquery = pm.newQuery(Employee.class, "(lastName == 'Smith' || lastName ==
'Jones')" + " && firstName == 'Harold'");
ATENCIN: importantes restricciones en las consultas, revisar:
http://code.google.com/intl/es/appengine/docs/java/datastore/queriesandindexes.ht
ml#Restrictions_on_Queries
Ejemplo: Los filtros de desigualdad slo estn permitidos en una propiedad

60. Ejemplo Objeto Serializable
La siguiente clase define un objeto que puede serializarse en JDO:
importjava.io.Serializable;
publicclassDownloadableFileimplementsSerializable{
private byte[] content;
privateStringfilename;
privateStringmimeType; // ... accessors ...
}
La siguiente clase define cmo usarlo:
importjavax.jdo.annotations.Persistent;
importDownloadableFile;
// ...
@Persistent(serialized = "true");
privateDownloadableFilefile;

61. Ejemplo Relacin 1 a 1 entre Entidades
importcom.google.appengine.api.datastore.Key;
// ... imports ...
@PersistenceCapable
publicclassContactInfo {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
privateStringstreetAddress;
@Persistent
privateStringcity;
@Persistent
privateStringstateOrProvince;
@Persistent
privateStringzipCode;
// ... accessors ...
}
importContactInfo;
// ... imports ...
@PersistenceCapable
publicclassEmployee {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
privateContactInfomyContactInfo;
// ... accessors ...
}

62. Relaciones Uno a Varios
Ejemplo de relacin bidireccional uno a varios:
// Employee.java
importjava.util.List;
// ...
@Persistent
private List<ContactInfo> contactInfoSets;
// ContactInfo.java
importEmployee;
// ...
@Persistent
privateEmployeeemployee;

63. Relaciones Varios a Varios
Ejemplo de relacin varios a varios, slo se puede hacer guardando colecciones de
claves en ambas relaciones implicadas:
//Person.java
importjava.util.Set;
importcom.google.appengine.api.datastore.Key;
// ...
@Persistent
private Set<Key> favoriteFoods;
//Food.java
importjava.util.Set;
importcom.google.appengine.api.datastore.Key;
// ...
@Persistent
private Set<Key> foodFans;
// Album.java
// ...
publicvoidaddFavoriteFood(Foodfood) {
favoriteFoods.add(food.getKey());
food.getFoodFans().add(getKey());
}
publicvoidremoveFavoriteFood(Foodfood) {
favoriteFoods.remove(food.getKey());
food.getFoodFans().remove(getKey());
}

64. Caractersticas Avanzadas de Google AppEngine
Planificacin de tareas con Cron for Java
http://code.google.com/appengine/docs/java/config/cron.html
Memcache Java API
http://code.google.com/appengine/docs/java/memcache/overview.html
URL Fech Java API
http://code.google.com/appengine/docs/java/urlfetch/overview.html
Envo de mensajes instantneos con XMPP e email
http://code.google.com/appengine/docs/java/xmpp/overview.html
Colas de tareas permite ejecutar asncronamente tareas
http://code.google.com/appengine/docs/java/taskqueue/overview.html

65. Planificacin de Tareas con Cron
El servicio AppEngine Cron Service permite planificar tareas que se ejecutan en un
momento o periodos determinados.
Los trabajos cron (cron jobs) son ejecutados por AppEngine Cron Service
Algunos ejemplos de uso seran:
Envo de email con informe diario
Actualizacin de tu cach de datos cada 10 minutos
Documentacin en: http://code.google.com/appengine/docs/java/config/cron.html
Formato de las planificaciones:
("every"|ordinal) (days) ["of" (monthspec)] (time)

66. Planificacin de Tareas con Cron
El fichero WEB-INFcron.xmlcontrolacronparatuaplicacin:
<?xmlversion="1.0" encoding="UTF-8"?>
<cronentries>
<cron> <url>/recache</url> <description>Repopulatethe cache every 2
minutes</description> <schedule>every 2 minutes</schedule></cron><cron>
<url>/weeklyreport</url> <description>Mail out a
weeklyreport</description> <schedule>everymonday
08:30</schedule> <timezone>America/New_York</timezone></cron>
</cronentries>

67. Memcache Java API
Las aplicaciones web escalables de alto rendimiento utilizan a menudo una cach
distribuida de datos integrados en memoria delante o en lugar de un sistema de
almacenamiento complejo permanente para algunas tareas
AppEngine incluye un servicio de memoria cach
El API Java de Memcache implementa la interfaz JCache (javax.cache), un estndar en
formato borrador descrito en JSR 107
JCache proporciona una interfaz en forma de mapa para recopilar datos
Puedes almacenar y recuperar valores de la memoria cach mediante las claves
Controlar cundo los valores vencen en la memoria cach
Inspeccionar el contenido de la memoria cach y obtener estadsticas sobre ella
Utilizar "funciones de escucha" para aadir un comportamiento personalizado al
establecer y borrar valores.

Pasos para Hacer uso de Memcache
Obtencin y configuracin de una instancia de Cache, para ello hay que configurar los
parmetros del mtodo createCache
importjavax.cache.Cache;
importjavax.cache.CacheException;
importjavax.cache.CacheFactory;
// ...
Cache cache;
try {
Mapprops = new Map;
props.put(GCacheFactory.EXPIRATION_DELTA, 3600);
props.put(MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT, true);
CacheFactorycacheFactory = CacheManager.getInstance().getCacheFactory();
// cache = cacheFactory.createCache(Collections.emptyMap());
cache = cacheFactory.createCache(props);
} catch (CacheException e) { // ... }
Establecimiento y obtencin de valores.
Se comporta como un mapa
Puedes almacenar claves y valores a travs del mtodo put() y recuperar valores con el
mtodo get()
Otros mtodos de inters son: remove(), clear(), containsKey(), isEmpty() y size()
Ms documentacin en:
http://code.google.com/intl/es/appengine/docs/java/memcache/usingjcache.html

69. URL Fetch Java API
GAE permite realizar conexiones HTTP y HTTPS a travs del servicio URL Fetch, que en
el caso de GAE for Java se implementa mediante la clase java.net.URLConnection
La funcionalidad que da es:
Acceso sencillo a los contenidos de una pgina mediante java.net.URL y el mtodo
openStream()
El mtodo openConnection() de java.net.URL devuelve una instancia de
HttpURLConnection, sobre la que se puede hacer getInputStream() y
getOutputStream()
Se pueden cambiar propiedades de la conexin como:
Aadir cabeceras: connection.setRequestProperty("X-MyApp-Version", "2.7.3");
Modificar el hecho de que las peticiones se redirijan directamente:
connection.setRequestProperty("X-MyApp-Version", "2.7.3");
Ms detalles en:
http://code.google.com/intl/en/appengine/docs/java/urlfetch/usingjavanet.html

Mail Java API
Una aplicacin en AppEngine puede enviar mensajes en representacin del
administrador de la pgina o de usuarios autorizados con cuentas Google
La Mail Service Java API hace uso de javax.mail
Se puede configurar tu aplicacin para recibir mensajes en una direccin con el
formato string@appid.appspotmail.com
Cuando una aplicacin se ejecuta en el servidor de desarrollo, el mensaje enviado se
imprime en el log, no se enva

Enviando un Mensaje
...
importjava.util.Properties;
importjavax.mail.Message;
importjavax.mail.MessagingException;
importjavax.mail.Session;
importjavax.mail.Transport;
importjavax.mail.internet.AddressException;
importjavax.mail.internet.InternetAddress;
importjavax.mail.internet.MimeMessage;
// ...
Propertiesprops = new Properties();
Sessionsession = Session.getDefaultInstance(props, null);
StringmsgBody = "...;
try {
Messagemsg = new MimeMessage(session);
msg.setFrom(new InternetAddress("admin@example.com", "Example.com Admin"));
msg.addRecipient(Message.RecipientType.TO, new
InternetAddress("user@example.com", "Mr. User"));
msg.setSubject("Your Example.com account has beenactivated");
msg.setText(msgBody);
Transport.send(msg);
} catch (AddressException e) {
// ...
} catch (MessagingException e) {
// ...
}

72. Recibiendo un Mensaje
Los pasos a seguir son:
Configurar tu aplicacin para ser receptora de email en la direccin:
string@appid.appspotmail.com
Modificando el fichero appengine-web.xml:
<inbound-services>
<service>mail</service>
</inbound-services>
Modificando el fichero web.xml, que recibir mensajes en la siguiente direccin:
/_ah/mail/<address>
<servlet>
<servlet-name>mailhandler</servlet-name>
<servlet-class>MailHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mailhandler</servlet-name>
<url-pattern>/_ah/mail/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<url-pattern>/_ah/mail/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>

Recibiendo un Mensaje
Los pasos a seguir son:
Crear un servlet que reciba los mensajes
importjava.io.IOException;
importjava.util.Properties;
importjavax.mail.Session;
importjavax.mail.internet.MimeMessage;
importjavax.servlet.http.*;
publicclassMailHandlerServletextendsHttpServlet{
publicvoiddoPost(HttpServletRequestreq, HttpServletResponseresp)
throwsIOException {
Propertiesprops = new Properties();
Sessionsession = Session.getDefaultInstance(props, null);
MimeMessagemessage = new MimeMessage(session, req.getInputStream());

}

TaskQueue API
Una aplicacin Java puede crear una cola configurada en el fichero de configuracin
WEB-INF/queue.xml
Para encolar una tarea, hay que obtener una instancia de Queue usando una
QueueFactory y luego invocar el mtodo add()
Puedes obtener una cola por nombre declarada en el fichero queue.xml o la cola por
defecto con el mtodo getDefaultQueue()
Se puede aadir una tarea a la cola pasando una instancia de TaskOptions al mtodo
add()
Se invocar un servlet que ser quien ejecute la tarea encolada (ver ejemplo siguiente
trasparencia)
Espacio de nombres en versin beta: com.google.appengine.api.labs.taskqueue

75. Ejemplo de TaskQueue API
El siguiente ejemplo muestra cmo aadir una tarea a una cola:
importcom.google.appengine.api.labs.taskqueue.Queue;
importcom.google.appengine.api.labs.taskqueue.QueueFactory;
importstaticcom.google.appengine.api.labs.taskqueue.TaskOptions.Builder.*;
// ...
Queuequeue = QueueFactory.getDefaultQueue();
queue.add(url("/worker").param("key", key));

76. Ejemplo de TaskQueue API
Ejemplo de queue.xml, donde s indica segundos, m minutos, h horas y d das, es decir,
la frecuencia con la que las tareas encoladas seran procesadas:
<queue-
entries> <queue> <name>default</name> <rate>1/s</rate> </queue> <queue>
<name>mail-queue</name> <rate>2000/d</rate> <bucket-size>10</bucket-
size> </queue> <queue> <name>background-
processing</name> <rate>5/s</rate> </queue></queue-entries>

Combinando Struts2 y GAE
Revisar ejemplo: struts2tutorial
Modificaciones a realizar en la distribucin de struts2tutorial:
Reimplementar la clase freemarker.core.TextBlock
Inicializar a null el SecurityManager de OgnlRuntime
Explicacin de cmo hacerlo en:
http://whyjava.wordpress.com/2009/08/30/creating-struts2-application-on-google-
app-engine-gae/

Plugin for Eclipse for Java
Instrucciones en: http://code.google.com/eclipse/docs/download.html
Descarga Eclipse Galileo for Java Developers de: http://www.eclipse.org/downloads/

Importacin y Exportacin de Datos
Se pueden acceder a datos detrs de tu Intranet desde una aplicacin de Google
AppEngine, con Google Secure Data Connector y el servicio urlfetch
(com.google.appengine.api.urlfetch.*)
http://code.google.com/intl/en/securedataconnector/docs/1.3/tutorials/appengine.ht
ml
Se pueden importar y exportar datos del datastore en forma de ficheros CSV
Solamente disponible en Python de momento:
http://code.google.com/appengine/docs/python/tools/uploadingdata.html

Google AppEngine for Business
Las aplicaciones generadas con AppEngine for Business usan las APIs de Java y Python,
pero permiten acceder al desarrollador a capacidades especiales (premium):
Acceso a SSL y SQL
Tendrn un coste adicional
Mas informacin en: http://code.google.com/appengine/business/

El servicio tiene varias limitaciones:
Solo hasta recientemente no todo el mundo poda acceder a l
Es gratis durante el periodo de pruebas, pero con lmites de uso: 500 MB de
almacenamiento, 200 millones de megaciclos/da y 10 Gb de ancho de banda
Google cobra para webs que requieren alta escalabilidad
Existen escasas aplicaciones comerciales desarrolladas en esta plataforma
Repositorio de ejemplos: http://appgallery.appspot.com/
VOSAO CMS - http://www.vosao.org/

Limitaciones tcnicas originales parcialmente resueltas:

Los desarrolladores solamente tienen acceso de lectura al sistema de ficheros
de AppEngine
Solamente se puede ejecutar cdigo a partir de una peticin HTTP
Solamente se puede subir cdigo puramente Python (resuelto con soporte
Java)
No se puede descargar o ejecutar scripts en su base de datos (remote_api)
Las aplicaciones deben ser escritas en Python o Java

Google AppEngine es una plataforma mucho ms acoplada y menos flexible
Si quieres hacer uso de BigTable tienes que escribir y desplegar un script de Python a
su servidor de aplicaciones ofreciendo una interfaz web accesible a BigTable (resuelto
parcialmente)

Referencias
Google AppEngine
http://code.google.com/appengine/

Você também pode gostar