Engine
31 de Mayo de 2011, 18:00-21:00
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)
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
Ejemplo:
https://appengine.google.com
5
http://enpresadigitala.appspot.com/encuestas
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
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
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
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
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.
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:
27
Funcionalidad de
AppEngine for Java
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
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
Dos opciones:
34
Paso 3: Creando el
fichero de despliegue
web.xml
36
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
Usando el Servicio de
Usuarios
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
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>
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
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
Funcionamiento de JDO
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
Cada solicitud que utiliza el almacn de datos crea una nueva instancia de
la clase PersistenceManager que se obtiene a travs de
PersistenceManagerFactory
Para guardar la instancia en el almacn de datos, crea una clase PersistenceManagera travs
50
de PMF.get() e invocamos sobre lmakePersistent()
51
<%
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
Creando de Objetos y
Claves
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");
Actualizacin y Borrado
de Objetos
Realizando Consultas
con JDO
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
58
Ejemplo Objeto
Serializable
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
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
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
Documentacin en:
http://code.google.com/appengine/docs/java/confi
g/cron.html
Formato de las planificaciones:
Planificacin de Tareas
con Cron
2.
3.
Ms documentacin en:
http://code.google.com/intl/es/appengine/docs/java/memcache/usingjcac
67
he.html
Ms detalles en:
http://code.google.com/intl/en/appengine/docs/java/urlfetch
68
/usingjavanet.html
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
b.
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
74
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
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
79
Limitaciones Google
App Engine
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)
82
Referencias
83
84