Vous êtes sur la page 1sur 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

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)

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
3
application without having
to babysit it.

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


4
desarrolladores pueden hacer uso de componentes existentes

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
5
http://enpresadigitala.appspot.com/encuestas

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 correo
electrnico

destinatarios

0,0001 dlares

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

GAE for Python:


Instalacin
Descargar Google App Engine SDK para
Python de:
http://code.google.com/appengine/downlo
ads.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
9
datos en ficheros CSV
al almacen de datos de

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
15
pet.put()

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.

2.
3.

Editar el ficheroapp.yamlfile y cambiar el valor de la


aplicacin:de helloworldal nombre de id de
aplicacin (enpresadigitala)
Ejecutar el siguiente comando: appcfg.py update
helloworld/
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:

Es conveniente cambiar las siguientes configuraciones en Django:

Importar util de google.appengine.ext.webapp


Importar WSGI handler de Django
[OPCIONAL] Redirigir los logs a la Admin Console de Google App Engine
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 estndarcomo JDO, JPA,
JavaMail y JCache

App Engine utilizael estndar Java Servletpara


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: losobjetos de datos Java(JDO) 2.3 y elAPI
de persistencia de Java(JPA) 1.0.
Acceder a recursos en la red. A travs de la URL Fectch API.
Cachear informacin. Memcachede 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
utilizarCuentas de Googlepara la autenticacin del usuario.
Lanzar tareas planificadas o en background. Mediante la Task
29
Queue Java API y la gestin de tareas
por Cron.

Instalacin de AppEngine
for Java
1. Descargar el fichero de:
http://code.google.com/intl/es/appengine/do
wnloads.html#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 aplicacin31al dominio

Configuracin del
Entorno
1.
2.

Instalar java
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.1bin.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:

Las aplicaciones Java de App Engine utilizan elAPI Java Servletpara


interactuar con el servidor web.

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

Un servlet HTTP es una clase de aplicacin que puede procesar y responder


solicitudes web. Esta clase ampla la clase javax.servlet.GenericServleto 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...
33
lib/

Paso 2: Creando la clase


Servlet

Crear en el directoriosrc/guestbook/un fichero


denominadoGuestbookServlet.javacon 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.xmly se ubica en el directoriowar/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 aweb.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 denominadoappengineweb.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 archivoappengine-web.xmly, 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
38

El fichero de Ant

Apache Antfacilita 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 newproject-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 directoriowar/, crea un archivo llamadoguestbook.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>
43
</servlet-mapping>

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.Loggerpara escribir


mensajes en el registro.
Puedes controlar el comportamiento de esta clase a travs de un
archivologging.propertiesy de un conjunto de propiedades del sistema
en el archivo appengine-web.xmlde la aplicacin.

Copia el archivo de ejemplo del SDKappengine-javasdk/config/user/logging.propertiesen el directoriowar/WEB-INF/de la


aplicacin

Para modificar el nivel de registro de todas las clases del paqueteguestbook, edita el
archivologging.propertiesy aade una entrada paraguestbook.level, como se
muestra a continuacin:
.level = WARNING
guestbook.level = INFO

A continuacin edita el archivowar/WEB-INF/appengine-web.xmlde 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="WEBINF/logging.properties"/>
</system-properties>
</appengine-web-app>

Los ficheros de logeo se descargan con la consola de administracin o la


45
aplicacin

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)
yAPI de persistencia Java(JPA).
Estas interfaces las proporcionaDataNucleus 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 claseGreetingrepresentar
mensajes
47
individuales publicados en el libro de invitados de nuestra

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,contentydate
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
claveLongque presenta dos
anotaciones:@Persistenty@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/datasto
49
re/dataclasses.html

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 deGreetingmediante la


ejecucin del constructor.

Para guardar la instancia en el almacn de datos, crea una clase PersistenceManagera travs
50
de PMF.get() e invocamos sobre lmakePersistent()

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 deWEB-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
archivoappengine-web.xml
La siguiente pgina da ms informacin al respecto:
http://code.google.com/intl/es/appengine/docs/java/config/appconfig.ht
ml

Para este ejemplo:

Crear main.css con el siguiente contenido:


body { font-family: Verdana, Helvetica, sans-serif; background-color:
#FFFFCC; }
53

Aadir a guestbook.jsp lo siguiente:

Creando de Objetos y
Claves

Para almacenar un objeto de datos sencillo en el almacn de datos, ejecuta


el mtodomakePersistent()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,
54
"Alfred.Smith@example.com");

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/
queriesandindexes.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/overvi
ew.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.ht
ml

Colas de tareas permite ejecutar asncronamente tareas


http://code.google.com/appengine/docs/java/taskqueue/overvi
ew.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/confi
g/cron.html
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
enJSR 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
66y borrar valores.
personalizado al establecer

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.

3.

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/usingjcac
67
he.html

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-MyAppVersion", "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
68
/usingjavanet.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
69
se imprime en el log, no se enva

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>
75
</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/creat
ing-struts2-application-on-google-app-enginegae/
76

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/

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/securedataconne
ctor/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:
78
http://code.google.com/appengine/docs/python/tools/

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)
80
Las aplicaciones deben ser escritas en Python o Java

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
81
BigTable (resuelto parcialmente)

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