Você está na 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

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 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 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
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/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
Crear el directorio helloworld
Crea el fichero helloworld.py dentro de l con el siguiente contenido, que
corresponde a una respuesta HTTP:

1.
2.

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/

5.

El switch --help da ms indicaciones sobre las opciones aceptadas por el servidor

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 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 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 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/<nombreaplicacin>
7. Subir la aplicacin al dominio appspot.com
31

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 el API Java Servlet para 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.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 appengineweb.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 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 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-javasdk/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="WEBINF/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() {
pmfInstance;
}

return

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,
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/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
Obtencin y configuracin de una instancia de Cache, para ello hay que configurar los
parmetros del mtodo createCache

1.

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/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-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/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>
71
</security-constraint>

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/creatingstruts2-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

Você também pode gostar