Escolar Documentos
Profissional Documentos
Cultura Documentos
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:
https://appengine.google.com
http://enpresadigitala.appspot.com/encuestas
5
http://code.google.com/intl/en/appengine/docs/
Unidad
Coste de la unidad
gigabytes
0,12 dlares
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
Crear el directorio helloworld
Crea el fichero helloworld.py dentro de l con el siguiente contenido, que
corresponde a una respuesta HTTP:
1.
2.
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.
5.
12
13
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()
16
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
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:
26
27
28
Funcionalidad de AppEngine
for Java
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:
Las aplicaciones Java de App Engine utilizan el API Java Servlet para interactuar con el
servidor web.
Un servlet HTTP es una clase de aplicacin que puede procesar y responder solicitudes web. Esta
clase ampla la clase javax.servlet.GenericServlet o a la
clase javax.servlet.http.HttpServlet.
34
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
App Engine necesita un archivo de configuracin adicional para poder desarrollar y ejecutar
la aplicacin, denominado appengine-web.xml
36
37
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
39
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
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
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
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
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.
Cada solicitud que utiliza el almacn de datos crea una nueva instancia de la clase
PersistenceManager que se obtiene a travs de PersistenceManagerFactory
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
51
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
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
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
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
}
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'");
58
60
61
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
63
Documentacin en:
http://code.google.com/appengine/docs/java/config/cron.ht
ml
Formato de las planificaciones:
("every"|ordinal) (days) ["of" (monthspec)] (time)
64
66
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.
3.
Ms documentacin en:
http://code.google.com/intl/es/appengine/docs/java/memcache/usingjcache.html
67
Ms detalles en:
http://code.google.com/intl/en/appengine/docs/java/urlfetch/usingjavan
68
et.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.
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
73
74
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
79
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
82
Referencias
Google App Engine
http://code.google.com/appengine/
83
84