Está en la página 1de 84

Cloud Computing: Google App Engine

31 de Mayo de 2011, 18:00-21:00


Dr. Diego Lz. de Ipia Glz. de Artaza
dipina@deusto.es
http://paginaspersonales.deusto.es/dipina
http://www.slideshare.net/dipina
http://www.morelab.deusto.es

1
Agenda
1. Ejemplo de PaaS: Google App Engine (180)
Introduccin (15)
DataStore API y GQL (25)
Memcache y Cron (20)
Versiones Python y Java de Google App Engine (60)
Desarrollo de una aplicacin de ejemplo sobre GoogleApp
(60)

2
Google App Engine
All the power of Google in one, simple platform.
Zero to sixty: App Engine enables your application to scale
automatically without worrying about managing machines.
Supercharged APIs: The App Engine platform provides
amazing services such as Task Queue, XMPP, and
Propsective search, all powered by the same infrastructure
that powers Google's applications.
You're in control: The simple, web-based dashboard
makes it easy to manage your application without having
to babysit it.

3
Ejemplo Plataforma Cloud:
Google App Engine
Google App Engine es una herramienta para el alojamiento de
aplicaciones web escalables sobre la infraestructura de Google
Su misin es permitir al desarrollador web crear fcilmente aplicaciones web
escalables sin ser un experto en sistemas
Aporta las siguientes caractersticas a los desarrolladores:
Limita la responsabilidad del programador al desarrollo y primer despliegue
Google App Engine provee recursos computacionales dinmicamente segn
son necesarios
Toma control de los picos de trfico si nuestro portal crece en popularidad
no es necesario actualizar nuestra infraestructura (servidores, BBDD)
Ofrece replicacin y balanceo de carga automtica apoyado en componentes como
Bigtable
Fcilmente integrable con otros servicios de Google los desarrolladores
pueden hacer uso de componentes existentes y la librera de APIs de Google
(email, autenticacin, pagos, etc.)
4
Google App Engine:
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 App Engine 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
5
http://code.google.com/intl/en/appengine/docs/
Facturacin Google App Engine
Hasta 10 aplicaciones con 500 MB de almacenamiento y 5 millones de visitas al
mes cada una
Pgina de presupuestado y facturacin de recursos:
http://code.google.com/intl/es/appengine/docs/billing.html
Detalles sobre las cuotas en:
http://code.google.com/intl/es/appengine/docs/quotas.html

Recurso Unidad Coste de la unidad

Ancho de banda de salida gigabytes 0,12 dlares

Ancho de banda de entrada gigabytes 0,10 dlares

Tiempo de CPU horas de CPU 0,10 dlares

Datos almacenados gigabytes al mes 0,15 dlares

Destinatarios de mensajes de destinatarios 0,0001 dlares


correo electrnico

6
7
Google App Engine: 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

8
GAE for Python: Instalacin
Descargar Google App Engine SDK para Python de:
http://code.google.com/appengine/downloads.html
Herramientas de la SDK para Python:
dev_appserver.py, el servidor web de desarrollo
appcfg.py, sirve para subir tu aplicacin a App Engine
Herramienta de descarga de datos es una herramienta
sencilla que te permite subir datos en ficheros CSV al
almacen de datos de appengine
http://code.google.com/intl/es/appengine/docs/python/tools/up
loadingdata.html

9
Principios
Una aplicacin de App Engine 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

10
Mi primera aplicacin
1. Crear el directorio helloworld
2. 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!
3. Crea el fichero de configuracin requerido por toda aplicacin App Engine 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
4. Arranca el servidor con el comando: dev_appserver.py helloworld/
El switch --help da ms indicaciones sobre las opciones aceptadas por el servidor
5. Vete a la siguiente URL para probarlo: http://localhost:8080/

11
Ejecutando Hola Mundo en
Google App Engine

12
Opciones Avanzadas para GAE for
Python
Framework webapp que soporta el estndar
WSGI
Acceso a datos de usuarios mediante la Users
API
DataStore API
Plantillas en Google App Engine

13
Usando el Almacn de Datos de
Google App Engine
Guardar datos en una aplicacin web escalable puede ser difcil
La infraestructura de App Engine 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 es relacional, todas las entidades de un mismo tipo tienen las mismas
propiedades
Una propiedad puede tener uno o varios valores
El siguiente import nos da acceso a la base de datos de Google
App Engine:
from google.appengine.ext import db
Para ms detalles sobre el DataStore API ir a:
http://code.google.com/appengine/docs/datastore/
14
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.
from google.appengine.ext import db
from google.appengine.api import users

class Pet(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 = 24
pet.put() 15
GQL Query Language
Para limpiar la base de datos creada: dev_appserver.py --
clear_datastore helloworld/
Ejemplo GQL:
if users.get_current_user():
user_pets = db.GqlQuery("SELECT * FROM Pet WHERE
pet.owner = :1, users.get_current_user())
for pet in user_pets:
pet.spayed_or_neutered = True

db.put(user_pets)

16
Usando plantillas en Google App
Engine
Empotrar HTML en cdigo es algo lioso y difcil de mantener.
Los sistemas de plantillas estn diseados para mantener HTML aparte en
otro fichero donde elementos con sintaxis especial indican dnde
deberan aparecer los datos de la aplicacin
Dentro de App Engine puede utilizarse cualquier motor de plantillas
empaquetndolo con el cdigo de tu aplicacin, webapp incluye el
mecanismo de plantillas de Django, donde se pueden pasar objetos del
modelo datos
Para utilizarlo hay que incluir los dos siguientes imports:
import os
from google.appengine.ext.webapp import template
Adems reemplazar las sentencias self.response.out.write por la
sentencia template.render(path, template_values), que toma
como parmetros de entrada:
El camino al fichero de la plantilla
Un diccionario de valores
Y retorna:
El texto a renderizar

17
Registrando la aplicacin

18
Verificacin de tu cuenta

19
Verificacin de tu Cuenta

20
Registrando la aplicacin en
appengine.google.com

21
Registrando la applicacin

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

23
Subiendo la aplicacin

24
Accediendo a la aplicacin

25
Programando Google App Engine
con Django
Google App Engine y Django tienen la habilidad de usar el estndar WSGI para ejecutar aplicaciones
Como consecuencia podemos utilizar la pila de Django en Google App Engine, incluso su parte de middleware
Lo nico que tenemos que hacer es cambiar los modelos de datos de Django para que usen la DataStore API de Google
App Engine
Como ambas APIs son muy similares, tenemos la misma flexibilidad usando la potencia de BigTable, es trivial adaptar un
modelo Django a Google App Engine
Adems como Google App Engine ya incluye Django, solamente hay que importar los mdulos que utilizaras normalmente
Para usar el gestor WSGI tenemos que realizar los siguientes pasos:
Importar util de google.appengine.ext.webapp
Importar WSGI handler de Django
[OPCIONAL] Redirigir los logs a la Admin Console de Google App Engine
Es conveniente cambiar las siguientes configuraciones en Django:
Dejar vacas las variables DATABASE_* de settings.py
Deshabilitar el middleware de session y autenticacin que hace uso de los modelos Django
Ms info en: http://code.google.com/appengine/articles/django.html
Revisar ejemplo de encuestas programado en Django para AppEngine en:
examples/googleappengine/python/djangosolopsiteappengine

26
Ejemplo Django Compleja sobre App
Engine

27
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
App Engine 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.

28
Funcionalidad de AppEngine
for Java
App Engine 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 App Engine 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 Task Queue Java API y la
gestin de tareas por Cron.

29
Instalacin de AppEngine for Java
1. Descargar el fichero de:
http://code.google.com/intl/es/appengine/downloads.ht
ml#Google_App_Engine_SDK_for_Java
2. Descomprimir el fichero .zip
3. Crear una variable de entorno
APPENGINE_JAVA_SDK que apunte al directorio
raz de instalacin de la SDK
4. Incluir el directorio
%APPENGINE_JAVA_SDK%\bin en la variable
de entorno PATH
30
Pasos para crear una Aplicacin
con Google App Engine para Java
1. Crear el proyecto de la aplicacin
2. Crear la clase servlet
3. Crear el fichero de despliegue de la aplicacin:
web.xml
4. Crear el archivo appengine-web.xml
5. Ejecutar el proyecto
6. Probar el proyecto: http://localhost:8080/<nombre-
aplicacin>
7. Subir la aplicacin al dominio appspot.com
31
Configuracin del Entorno
1. Instalar java
2. Descomprimir la distribucin de GAE for Java a una carpeta de tu disco
duro
3. Modificar la variable de entorno APPENGINE_JAVA_SDK para que
apunte a ese directorio
4. Modificar la variable de entorno PATH para que apunte a
%APPENGINE_JAVA_SDK%\bin
5. Descomprimir el fichero downloads\apache-ant-1.8.1-
bin.zip
6. Modificar la variable de entorno PATH para que apunte a
<ANT_DIR>\bin
7. cd examples\googleappengine\java\guestbook
8. ant

32
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%\demos\new_project_template
Las aplicaciones Java de App Engine 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 source code...
META-INF/
...other configuration...
war/
...JSPs, images, data files...
WEB-INF/
...app configuration...
classes/
...compiled classes...
lib/ 33
...JARs for libraries...
Paso 2: Creando la clase Servlet
Crear en el directorio src/guestbook/ un fichero
denominado GuestbookServlet.java con el siguiente contenido:
package guestbook;

import java.io.IOException;
import javax.servlet.http.*;

public class GuestbookServlet extends HttpServlet {


public void doGet(HttpServletRequest req,
HttpServletResponse resp) throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Hello, world");
}
}

34
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
<?xml version="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-app xmlns="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> 35
Paso 4: Crear el fichero de
configuracin de aplicacin GAE:
appengine-web.xml
App Engine 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:

<?xml version="1.0" encoding="utf-8"?>


<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>librocitas</application>
<version>1</version>
</appengine-web-app>

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

37
Paso 6: Subiendo la aplicacin
1. Puedes crear y administrar aplicaciones web App Engine con
la consola de administracin de App Engine a travs de la
siguiente URL: http://appengine.google.com/
2. Para crear una nueva aplicacin, haz clic en el botn "Create
an Application" (Crear aplicacin)
3. 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).
4. Ejecuta el siguiente comando en lnea de comandos para
subir la aplicacin: $ appcfg update www
5. Vete a: http://librocitas.appspot.com/

38
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 App Engine, entre las que se incluyen:
El inicio del servidor de desarrollo y
La subida de la aplicacin a App Engine
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

39
Usando el Servicio de Usuarios
Google App Engine 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

package guestbook;
import java.io.IOException;
import javax.servlet.http.*;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public class GuestbookServlet extends HttpServlet {


public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();

if (user != null) {
resp.setContentType("text/plain");
resp.getWriter().println("Hello, " + user.getNickname());
} else {
resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
}
}
}
40
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 App Engine, el SDK compila todas las JSP en cdigo de bytes
y nicamente sube el cdigo de bytes.

41
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><%
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
if (user != null) {%>
<p>Hello, <%= user.getNickname() %>! (You can<a href="<%=
userService.createLogoutURL(request.getRequestURI()) %>">sign
out</a>.)</p><%
} else {%>
<p>Hello!<a href="<%=
userService.createLoginURL(request.getRequestURI()) %>">Sign in</a>to
include your name with greetings you post.</p><%
}%>
</body>

42
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> 43
El Servlet que Procesa una Nueva
Entrada en Libro
package guestbook;
import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.http.*;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
public class SignGuestbookServlet extends HttpServlet {
private static final Logger log = Logger.getLogger(SignGuestbookServlet.class.getName());
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
String content = req.getParameter("content");
if (content == null) {
content = "(No greeting)";
}
if (user != null) {
log.info("Greeting posted by user " + user.getNickname() + ": " + content);
} else {
log.info("Greeting posted anonymously: " + content);
}
resp.sendRedirect("guestbook.jsp");
}
} 44
Logeo de Informacin con App
Engine
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-app xmlns="http://appengine.google.com/ns/1.0"> ...
<system-properties>
<property name="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 App Engine: https://appengine.google.com/logs
45
Uso del Almacen de Datos JDO
La infraestructura de App Engine 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.
App Engine for 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 App Engine.
Access Platform necesita un archivo de configuracin que le indique que debe utilizar
el almacn de datos de App Engine 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/

46
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 App Engine
permite almacenar instancias de clases definidas en el almacn de datos
de App Engine
Ejemplo: la clase Greeting representar mensajes individuales
publicados en el libro de invitados de nuestra aplicacin

47
La Clase de Persistencia Greeting
package guestbook;
import java.util.Date;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.users.User;
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Greeting {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
@Persistent
private User author;
@Persistent
private String content;
@Persistent
private Date date;
public Greeting(User author, String content, Date date) {
this.author = author;
this.content = content;
this.date = date;
}
...
48
}
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 App Engine.
La clase tambin define un campo llamado id, una clave Long que
presenta dos anotaciones: @Persistent y @PrimaryKey.
El almacn de datos de App Engine 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/dataclass
es.html

49
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 singleton PMF para resolverlo:
package guestbook;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
public final class PMF {
private static final PersistenceManagerFactory pmfInstance =
JDOHelper.getPersistenceManagerFactory("transactions-optional");

private PMF() {}
public static PersistenceManagerFactory get() { return
pmfInstance;
}
}
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() 50
Serializando datos con JDO
Dentro del fichero SignGuestBookServlet introduciramos los siguientes
cambios para serializar los saludos en App Engine DataStore, a travs de JDO:

String content = req.getParameter("content");


Date date = new Date();
Greeting greeting = new Greeting(user, content, date);
PersistenceManager pm = PMF.get().getPersistenceManager();

try {
pm.makePersistent(greeting);
} finally {
pm.close();
}

51
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>The guestbook has no messages.</p> <%
} else {
for (Greeting g : greetings) {
if (g.getAuthor() == null) { %>
<p>An anonymous person wrote:</p> <%
} else { %>
<p><b><%= g.getAuthor().getNickname() %></b> wrote:</p> <%
} %>
<blockquote><%= g.getContent() %></blockquote> <%

}
}
pm.close();
%> 52
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, App Engine muestra los archivos estticos desde
servidores independientes en lugar de los que ejecutan servlets.
App Engine 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 App Engine 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> 53
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.
import com.google.appengine.api.datastore.Key;
import com.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");
54
Actualizacin y Borrado de
Objetos
El siguiente cdigo muestra cmo actualizar un objeto persistente:
public void updateEmployeeTitle(User user, String newTitle) {
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);
55
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 App Engine.
Dos usos diferentes:
1. Puedes especificar parte o la totalidad de la consulta mediante mtodos de ejecucin en el objeto de
consulta
import java.util.List;
import javax.jdo.Query;
// ...
Query query = pm.newQuery(Employee.class);
query.setFilter("lastName == lastNameParam");
query.setOrdering("hireDate desc");
query.declareParameters("String lastNameParam");

try {
List<Employee> results = (List<Employee>) query.execute("Smith");
if (results.iterator().hasNext()) {
for (Employee e : results) {
// ...
}
} else {
// ... no results ...
}
} finally {
query.closeAll();
} 56
Realizando Consultas con JDO
2. Puedes especificar una consulta completa en una cadena mediante la
sintaxis de cadena JDOQL:
Query query = pm.newQuery("select from Employee " +
"where lastName == lastNameParam " +
"order by hireDate desc " +
"parameters String lastNameParam");
List<Employee> results = (List<Employee>)
query.execute("Smith");
3. Otro modo:
Query query = pm.newQuery(Employee.class,
"lastName == lastNameParam order by hireDate desc");
query.declareParameters("String lastNameParam");
List<Employee> results = (List<Employee>)
query.execute("Smith");

Query query = pm.newQuery(Employee.class,


"lastName == 'Smith' order by hireDate desc");

57
Filtros y Restricciones en
Consultas JDO sobre App Engine
Algunos ejemplos de filtros son:
query.setFilter("lastName == 'Smith' && hireDate >
hireDateMinimum");
query.declareParameters("Date hireDateMinimum");
Query query = 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/queriesandin
dexes.html#Restrictions_on_Queries
Ejemplo: Los filtros de desigualdad slo estn permitidos en una propiedad

58
Ejemplo Objeto Serializable
La siguiente clase define un objeto que puede serializarse en JDO:
import java.io.Serializable;
public class DownloadableFile implements Serializable {
private byte[] content;
private String filename;
private String mimeType;
// ... accessors ...
}

La siguiente clase define cmo usarlo:


import javax.jdo.annotations.Persistent;
import DownloadableFile;
// ...
@Persistent(serialized = "true");
private DownloadableFile file;

59
Ejemplo Relacin 1 a 1 entre
Entidades
import com.google.appengine.api.datastore.Key;
// ... imports ...
@PersistenceCapable
public class ContactInfo {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;

@Persistent
private String streetAddress;
@Persistent
private String city;
@Persistent
private String stateOrProvince;
@Persistent
private String zipCode;
// ... accessors ...
}

import ContactInfo;
// ... imports ...
@PersistenceCapable
public class Employee {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;

@Persistent
private ContactInfo myContactInfo;

// ... accessors ... 60


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

// ContactInfo.java
import Employee;
// ...
@Persistent
private Employee employee;

61
Relaciones Varios a Varios
Ejemplo de relacin varios a varios, slo se puede hacer guardando colecciones de claves en ambas relaciones implicadas:
//Person.java
import java.util.Set;
import com.google.appengine.api.datastore.Key;
// ...
@Persistent
private Set<Key> favoriteFoods;

//Food.java
import java.util.Set;
import com.google.appengine.api.datastore.Key;
// ...
@Persistent
private Set<Key> foodFans;

// Album.java
// ...
public void addFavoriteFood(Food food) {
favoriteFoods.add(food.getKey());
food.getFoodFans().add(getKey());
}
public void removeFavoriteFood(Food food) {
favoriteFoods.remove(food.getKey());
food.getFoodFans().remove(getKey());
}
62
Caractersticas Avanzadas de
Google App Engine
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

63
Planificacin de Tareas con Cron
El servicio App Engine Cron Service permite planificar tareas
que se ejecutan en un momento o periodos determinados.
Los trabajos cron (cron jobs) son ejecutados por App Engine 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.ht
ml
Formato de las planificaciones:
("every"|ordinal) (days) ["of" (monthspec)] (time)

64
Planificacin de Tareas con Cron
El fichero WEB-INF\cron.xml controla cron para tu aplicacin:
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/recache</url>
<description>Repopulate the cache every 2
minutes</description>
<schedule>every 2 minutes</schedule>
</cron>
<cron>
<url>/weeklyreport</url>
<description>Mail out a weekly report</description>
<schedule>every monday 08:30</schedule>
<timezone>America/New_York</timezone>
</cron>
</cronentries>
65
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
App Engine 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.

66
Pasos para Hacer uso de
Memcache
1. Obtencin y configuracin de una instancia de Cache, para ello hay que configurar los
parmetros del mtodo createCache
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheFactory;
// ...
Cache cache;
try {
Map props = new Map;
props.put(GCacheFactory.EXPIRATION_DELTA, 3600);
props.put(MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT, true);
CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
// cache = cacheFactory.createCache(Collections.emptyMap());
cache = cacheFactory.createCache(props);
} catch (CacheException e) { // ... }
2. 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()
3. Ms documentacin en:
http://code.google.com/intl/es/appengine/docs/java/memcache/usingjcache.html
67
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/usingjavan
68
et.html
Mail Java API
Una aplicacin en App Engine 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
69
Enviando un Mensaje
...
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
// ...
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
String msgBody = "...;
try {
Message msg = 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 been activated");
msg.setText(msgBody);
Transport.send(msg);
} catch (AddressException e) {
// ...
} catch (MessagingException e) {
// ...
70
}
Recibiendo un Mensaje
Los pasos a seguir son:
1. Configurar tu aplicacin para ser receptora de email en la direccin:
string@appid.appspotmail.com
a. Modificando el fichero appengine-web.xml:
<inbound-services>
<service>mail</service>
</inbound-services>
b. 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> 71
Recibiendo un Mensaje
Los pasos a seguir son:
2. Crear un servlet que reciba los mensajes
import java.io.IOException;
import java.util.Properties;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.*;
public class MailHandlerServlet extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse
resp) throws IOException {
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage message = new MimeMessage(session,
req.getInputStream());

}

72
Task Queue 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

73
Ejemplo de Task Queue API
El siguiente ejemplo muestra cmo aadir una tarea a una cola:
import com.google.appengine.api.labs.taskqueue.Queue;
import com.google.appengine.api.labs.taskqueue.QueueFactory;
import static
com.google.appengine.api.labs.taskqueue.TaskOptions.Builder
.*;

// ...
Queue queue = QueueFactory.getDefaultQueue();
queue.add(url("/worker").param("key", key));

74
Ejemplo de Task Queue 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> 75
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/

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

77
Importacin y Exportacin de
Datos
Se pueden acceder a datos detrs de tu Intranet
desde una aplicacin de Google App Engine, 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.html
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/uploadingd
ata.html
78
Google App Engine for Business
Las aplicaciones generadas con App Engine 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/

79
Limitaciones Google App
Engine
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 App
Engine
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
Guido van Rosum, creador de Python est detrs de Google App Engine

80
Google App Engine vs. Amazon
Web Services
A primera vista Google App Engine es un competidor
a la suite de servicios web ofrecida por Amazon:
S3 para almacenamiento
EC2 para la creacin de servidores virtuales
SimpleDB como base de datos
Pero
Google App Engine 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)
81
Google App Engine vs. Amazon
Web Services

82
Referencias
Google App Engine
http://code.google.com/appengine/

83
Cloud Computing: Google App Engine
31 de Mayo de 2011, 18:00-21:00
Dr. Diego Lz. de Ipia Glz. de Artaza
dipina@deusto.es
http://paginaspersonales.deusto.es/dipina
http://www.slideshare.net/dipina
http://www.morelab.deusto.es

84

También podría gustarte