SlideShare ist ein Scribd-Unternehmen logo
1 von 84
Cloud Computing: Google App Engine31 de Mayo de 2011, 18:00-21:00 Dr. Diego Lz. de Ipiña Glz. de Artazadipina@deusto.eshttp://paginaspersonales.deusto.es/dipinahttp://www.slideshare.net/dipinahttp://www.morelab.deusto.es
Agenda Ejemplo de PaaS: Google AppEngine (180’) Introducción (15’) DataStore API y GQL (25’) Memcache y Cron (20’) Versiones Python y Java de Google AppEngine(60’) Desarrollo de una aplicación de ejemplo sobre GoogleApp (60’)
Google AppEngine 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 AppEngine es una herramienta para el alojamiento de aplicaciones web escalables sobre la infraestructura de Google Su misión es permitir al desarrollador web crear fácilmente aplicaciones web escalables sin ser un experto en sistemas Aporta las siguientes características a los desarrolladores: Limita la responsabilidad del programador al desarrollo y primer despliegue –  Google AppEngine provee recursos computacionales dinámicamente según son necesarios Toma control de los picos de tráfico – si nuestro portal crece en popularidad no es necesario actualizar nuestra infraestructura (servidores, BBDD) Ofrece replicación y balanceo de carga automática apoyado en componentes como Bigtable Fácilmente integrable con otros servicios de Google – los desarrolladores pueden hacer uso de componentes existentes y la librería de APIs de Google (email, autenticación, pagos, etc.)
Google AppEngine:Características Ofrece una plataforma completa para el alojamiento y escalado automático 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 código Python o Java compilado a Google, lanzar la aplicación y monitorizar el uso y otras métricas Google AppEngine incluye la librería estándar 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 http://code.google.com/intl/en/appengine/docs/
Facturación Google AppEngine ,[object Object]
Página de presupuestado y facturación 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,[object Object]
Google AppEngine: Python y Java Vamos a revisar primero (brevemente) cómo realizar aplicaciones con Python Luego nos centraremos en cómo hacerlo desde Java en mayor grado de detalle
GAE forPython: Instalación Descargar Google AppEngine 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 aplicación a App Engine Herramienta de descarga de datos – esunaherramientasencillaquetepermitesubirdatos en ficheros CSV al almacen de datos de appengine http://code.google.com/intl/es/appengine/docs/python/tools/uploadingdata.html
Principios Una aplicación de AppEngine se comunica con el servidor que la aloja a través de CGI Cuando recibe una petición el servidor lee de la entrada estándar y de las variables de entorno Cuando genera una respuesta escribe a la salida estándar
Mi primera aplicación Crear el directorio helloworld 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!‘ Crea el fichero de configuración requerido por toda aplicación AppEngine 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 Arranca el servidor con el comando:dev_appserver.py helloworld/ ,[object Object],Vete a la siguiente URL para probarlo: http://localhost:8080/
Ejecutando Hola Mundo en Google App Engine
Opciones Avanzadas para GAE forPython Framework webapp que soporta el estándar WSGI  Acceso a datos de usuarios mediante la Users API DataStore API Plantillas en Google AppEngine
Usando el Almacén de Datos de Google AppEngine Guardar datos en una aplicación web escalable puede ser difícil La infraestructura de AppEngine se encarga de la distribución, replicación y balanceo de carga de los datos detrás de una API sencilla que también 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 detrás. No esrelacional, todaslasentidades de un mismotipotienenlasmismaspropiedades Unapropiedadpuedeteneruno o variosvalores El siguiente import nos da acceso a la base de datos de Google AppEngine:  fromgoogle.appengine.extimportdb Para más detalles sobre el DataStore API ir a: http://code.google.com/appengine/docs/datastore/
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. fromgoogle.appengine.extimportdbfromgoogle.appengine.apiimportusersclassPet(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 = 24pet.put()
GQL Query Language Para limpiar la base de datos creada: dev_appserver.py --clear_datastorehelloworld/ Ejemplo GQL: ifusers.get_current_user(): user_pets = db.GqlQuery("SELECT * FROM Pet WHERE pet.owner = :1“, users.get_current_user()) forpet in user_pets: pet.spayed_or_neutered = True   db.put(user_pets)
Usando plantillas en Google App Engine Empotrar HTML en código es algo lioso y difícil de mantener. Los sistemas de plantillas están diseñados para mantener HTML aparte en otro fichero donde elementos con sintaxis especial indican dónde deberían aparecer los datos de la aplicación Dentro de AppEngine puede utilizarse cualquier motor de plantillas empaquetándolo con el código de tu aplicación, 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 fromgoogle.appengine.ext.webappimporttemplate Además reemplazar las sentenciasself.response.out.write por la sentencia template.render(path, template_values), quetomacomoparámetros de entrada: El camino al fichero de la plantilla Un diccionario de valores Y retorna: El texto a renderizar
Registrando la aplicación
Verificación de tu cuenta
Verificación de tu Cuenta
Registrando la aplicación en appengine.google.com
Registrando la applicación
Subiendo la aplicación Es necesario realizar los siguientes pasos: Editar el fichero app.yaml file y cambiar el valor de la aplicación: de helloworld al nombre de id de aplicación (enpresadigitala) Ejecutar el siguiente comando: appcfg.py updatehelloworld/  Acceder a la aplicación en http://application-id.appspot.com, por ejemplo en http://enpresadigitala.appspot.com/
Subiendo la aplicación
Accediendo a la aplicación
Programando Google App Engine con Django Google AppEngine y Django tienen la habilidad de usar el estándar WSGI para ejecutar aplicaciones Como consecuencia podemos utilizar la pila de Django en Google AppEngine, 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 AppEngine Como ambas APIs son muy similares, tenemos la misma flexibilidad usando la potencia de BigTable, es trivial adaptar un modelo Django a Google AppEngine Además como Google AppEngine ya incluye Django, solamente hay que importar los módulos que utilizarías normalmente Para usar el gestor WSGI tenemos que realizar los siguientes pasos: Importar util de google.appengine.ext.webapp Importar WSGI handler de Django [OPCIONAL] Redirigir los logs a la AdminConsole de Google AppEngine Es conveniente cambiar las siguientes configuraciones en Django: Dejar vacías las variables DATABASE_* de settings.py Deshabilitar el middleware de session y autenticación que hace uso de los modelos Django Más info en: http://code.google.com/appengine/articles/django.html Revisar ejemplo de encuestas programado en Django para AppEngine en: examples/googleappengine/python/djangosolopsiteappengine
Ejemplo Django Compleja sobre AppEngine
AppEngine para Java Crea aplicaciones web a través de tecnologías estándar de Java y las ejecuta en la infraestructura escalable Google Usa JVM Java 6, interfaz de servlets Java y la compatibilidad de interfaces estándar como JDO, JPA, JavaMail y JCache AppEngine utiliza el estándar Java Servlet para aplicaciones web JVM se ejecuta en un entorno seguro de la "zona de pruebas" para aislar tu aplicación por servicio y seguridad.  Una aplicación en GAE sólo pueda realizar acciones que no interfieran con el rendimiento ni con la escalabilidad de otras aplicaciones. 
Funcionalidad de AppEnginefor Java AppEngine proporciona un conjunto de servicios escalables que pueden utilizar las aplicaciones para: Almacenar datos persistentes. En Java, el almacén de datos admite 2 interfaces Java estándar: 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 través de la URL Fectch API.  Cachear información. Memcache de AppEngine proporciona un almacenamiento en caché distribuido, transitorio y rápido de los resultados de cálculos y consultas de almacén de datos. La interfaz Java implementa JCache (JSR 107). Enviar email. Da soporte de JavaMail para el envío de correos Procesar imágenes. A través de la Images Java API, permite a las aplicaciones transformar y manipular datos de imágenes en varios formatos. Gestionar usuarios. A través de la Users Java API permite utilizar Cuentas de Google para la autenticación del usuario. Lanzar tareas planificadas o en background. Mediante la TaskQueue Java API y la gestión de tareas por Cron.
Instalación de AppEnginefor Java Descargar el fichero de: http://code.google.com/intl/es/appengine/downloads.html#Google_App_Engine_SDK_for_Java Descomprimir el fichero .zip Crear una variable de entorno APPENGINE_JAVA_SDK que apunte al directorio raíz de instalación de la SDK Incluir el directorio %APPENGINE_JAVA_SDK%inen la variable de entorno PATH
Pasos para crear una Aplicación con Google AppEngine para Java Crear el proyecto de la aplicación Crear la clase servlet Crear el fichero de despliegue de la aplicación: web.xml Crear el archivo appengine-web.xml Ejecutar el proyecto Probar el proyecto: http://localhost:8080/<nombre-aplicación>  Subir la aplicación al dominio appspot.com
Configuración del Entorno Instalar java Descomprimir la distribución de GAE for Java a una carpeta de tu disco duro Modificar la variable de entorno APPENGINE_JAVA_SDK para que apunte a ese directorio Modificar la variable de entorno PATH para que apunte a %APPENGINE_JAVA_SDK%in Descomprimir el fichero downloadspache-ant-1.8.1-bin.zip Modificar la variable de entorno PATH para que apunte a <ANT_DIR>in cdexamplesoogleappengineavauestbook ant
Paso 1: Creando la estructura del proyecto Dos opciones: Usar el plug-in para Eclipse: http://code.google.com/intl/es/appengine/docs/java/tools/eclipse.html Usar la plantilla de proyecto disponible en %APP_ENGINE_HOME%emosew_project_template Las aplicaciones Java de AppEngine utilizan el API Java Servlet para interactuar con el servidor web.  Un servlet HTTP es una clase de aplicación que puede procesar y responder solicitudes web. Esta clase amplía 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 sourcecode...       META-INF/          ...otherconfiguration...  war/      ...JSPs, images, data files...      WEB-INF/         ...appconfiguration...  classes/         ...compiledclasses...  lib/         ...JARsforlibraries...
Paso 2: Creando la clase Servlet Crear en el directorio src/guestbook/ un fichero denominado GuestbookServlet.java con el siguiente contenido: packageguestbook;importjava.io.IOException;importjavax.servlet.http.*;publicclassGuestbookServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq, HttpServletResponseresp) throwsIOException {      resp.setContentType("text/plain");      resp.getWriter().println("Hello, world");   }}
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 configuración conocido como "descriptor de implementación de la aplicación web".  Este archivo se denomina web.xml y se ubica en el directorio war/WEB-INF/ del directorio que contiene los ficheros de una aplicación web en Java <?xmlversion="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-appxmlns="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>
Paso 4: Crear el fichero de configuración de aplicación GAE: appengine-web.xml AppEngine necesita un archivo de configuración adicional para poder desarrollar y ejecutar la aplicación, denominado appengine-web.xml  Se ubica en WEB-INF/ junto a web.xml.  Incluye la ID registrada de la aplicación, el número de versión de la aplicación y listas de archivos que se deben tratar como archivos estáticos (por ejemplo, imágenes y CSS) y archivos de recursos (por ejemplo, JSP y otros datos de aplicación). El directorio war/WEB-INF/ incluye un archivo denominado appengine-web.xml que contiene lo siguiente: <?xmlversion="1.0" encoding="utf-8"?> <appengine-web-appxmlns="http://appengine.google.com/ns/1.0"> <application>librocitas</application>     <version>1</version> </appengine-web-app>
Paso 5: Ejecución del Proyecto El SDK de AppEngine incluye un servidor web de pruebas para depurar tu aplicación. El servidor simula los servicios y el entorno AppEngine, que incluyen restricciones en la zona de pruebas, el almacén de datos y los servicios. Con el fichero ant ejecuta: antrunserver Puedes detenerlo con Ctrl-C
Paso 6: Subiendo la aplicación Puedes crear y administrar aplicaciones web AppEngine con la consola de administración de AppEngine a través de la siguiente URL: http://appengine.google.com/ Para crear una nueva aplicación, haz clic en el botón "CreateanApplication" (Crear aplicación) Edita el archivo appengine-web.xml y, a continuación, cambia el valor del elemento <application> para que sea la ID registrada de tu aplicación (librocitas). Ejecuta el siguiente comando en línea de comandos para subir la aplicación: $ appcfg update www Vete a: http://librocitas.appspot.com/
El fichero de Ant Apache Ant facilita la administración de tu proyecto desde la línea 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 AppEngine, entre las que se incluyen: El inicio del servidor de desarrollo y  La subida de la aplicación a AppEngine Algunos problemas con el build.xml suministrado por new-project-template Fichero adaptado en examples/guestbook/build.xml: Hay que definir variable de entorno APP_ENGINE_SDK para desligar build.xml de su localización en disco Introducir tarea para copiar jars con dependencias
Usando el Servicio de Usuarios Google AppEngine ofrece varios servicios útiles basados en la infraestructura de Google a los que se puede acceder a través 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 aplicación con cuentas de usuarios de Google packageguestbook;importjava.io.IOException;importjavax.servlet.http.*;importcom.google.appengine.api.users.User;importcom.google.appengine.api.users.UserService;importcom.google.appengine.api.users.UserServiceFactory;publicclassGuestbookServletextendsHttpServlet {    publicvoiddoGet(HttpServletRequestreq, HttpServletResponseresp)              throwsIOException {        UserServiceuserService = UserServiceFactory.getUserService();        Useruser = userService.getCurrentUser();        if (user != null) {            resp.setContentType("text/plain");            resp.getWriter().println("Hello, " + user.getNickname());        } else {            resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));        }    }}
Uso de un JSP Aunque podríamos generar el código HTML para la interfaz de usuario directamente a partir del código Java del servlet, no sería algo fácil de mantener, ya que el código HTML se complica Es más conveniente utilizar un sistema de plantillas, en el que la interfaz de usuario esté diseñada e implementada en archivos independientes con marcadores y lógica para insertar datos proporcionados por la aplicación. 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 código fuente Java y, a continuación, compila este código en código de bytes de Java Al subir la aplicación a AppEngine, el SDK compila todas las JSP en código de bytes y únicamente sube el código de bytes.
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><%  UserServiceuserService = UserServiceFactory.getUserService();    Useruser = userService.getCurrentUser();     if (user != null) {%>       <p>Hello, <%= user.getNickname() %>! (You can<a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">signout</a>.)</p><%         } else {%>       <p>Hello!<a href="<%= userService.createLoginURL(request.getRequestURI()) %>">Sign in</a>toincludeyournamewithgreetingsyou post.</p><%         }%>   </body>
Formulario Libro Invitados La aplicación 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 código 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>
El Servlet que Procesa una Nueva Entrada en Libro packageguestbook; importjava.io.IOException; importjava.util.logging.Logger; importjavax.servlet.http.*; importcom.google.appengine.api.users.User; importcom.google.appengine.api.users.UserService; importcom.google.appengine.api.users.UserServiceFactory; publicclassSignGuestbookServletextendsHttpServlet { privatestatic final Logger log = Logger.getLogger(SignGuestbookServlet.class.getName()); publicvoiddoPost(HttpServletRequestreq, HttpServletResponseresp)				throwsIOException{ UserServiceuserService = UserServiceFactory.getUserService();		 Useruser = userService.getCurrentUser();		 Stringcontent = req.getParameter("content");	 if (content == null) {			 content = "(No greeting)";		     }		 if (user != null) {			       log.info("Greetingpostedbyuser " + user.getNickname() + ": " + content);     } else {			       log.info("Greetingpostedanonymously: " + content);		     }		 resp.sendRedirect("guestbook.jsp");	   } }
Logeo de Información con AppEngine El nuevo servlet utiliza la clase java.util.logging.Logger para escribir mensajes en el registro. Puedes controlar el comportamiento de esta clase a través de un archivo logging.properties y de un conjunto de propiedades del sistema en el archivo appengine-web.xml de la aplicación. Copia el archivo de ejemplo del SDK appengine-java-sdk/config/user/logging.properties en el directorio war/WEB-INF/ de la aplicación  Para modificar el nivel de registro de todas las clases del paquete guestbook, edita el archivo logging.properties y añade una entrada para guestbook.level, como se muestra a continuación: .level = WARNING guestbook.level = INFO A continuación edita el archivo war/WEB-INF/appengine-web.xml de la aplicación como se indica: <appengine-web-appxmlns="http://appengine.google.com/ns/1.0"> ...    <system-properties>      <propertyname="java.util.logging.config.file" value="WEB-INF/logging.properties"/>    </system-properties> </appengine-web-app> Los ficheros de logeo se descargan con la consola de administración o la aplicación  appcfg de AppEngine: https://appengine.google.com/logs
Uso del Almacen de Datos JDO La infraestructura de AppEngine se encarga de todas las tareas de distribución, replicación y balanceo de carga de los datos de un API sencilla, además de ofrecer un potente motor de consulta y transacciones. Ofrece dos API: un API estándar y otra de nivel inferior. AppEnginefor Java permite el uso de dos estándares de API diferentes para el almacén de datos: Objetos de datos Java (JDO) y API de persistencia Java (JPA). Estas interfaces las proporciona DataNucleus Access Platform, una implementación de software libre de varios estándares de persistencia Java, con un adaptador para Google DataStore Utilizaremos la interfaz JDO para la recuperación y la publicación de los mensajes de los usuarios en el almacén de datos de AppEngine. Access Platformnecesita un archivo de configuración que le indique que debe utilizar el almacén de datos de AppEngine como servidor para la implementación de JDO: META-INF/jdoconfig.xml Documentación detallada de JDO puede encontrarse en: http://code.google.com/appengine/docs/java/datastore/
Funcionamiento de JDO Al crear clases JDO, debes utilizar anotaciones Java para describir cómo se deben guardar las instancias en el almacén de datos y cómo se deben volver a crear al recuperarlas de dicho almacén.  Access Platform conecta las clases de datos a la implementación mediante un paso de procesamiento posterior a la compilación, que DataNucleus denomina "mejora" de las clases. JDO permite almacenar objetos Java (a veces denominados "objetos Java antiguos y simples" o POJO) en cualquier almacén de datos con un adaptador compatible con JDO, como DataNucleus Access Platform El complemento Access Platform para el almacén de datos de AppEngine permite almacenar instancias de clases definidas en el almacén de datos de AppEngine Ejemplo: la clase Greeting representará mensajes individuales publicados en el libro de invitados de nuestra aplicación
La Clase de Persistencia Greeting packageguestbook; importjava.util.Date; importjavax.jdo.annotations.IdGeneratorStrategy; importjavax.jdo.annotations.IdentityType; importjavax.jdo.annotations.PersistenceCapable; importjavax.jdo.annotations.Persistent; importjavax.jdo.annotations.PrimaryKey; importcom.google.appengine.api.users.User; @PersistenceCapable(identityType = IdentityType.APPLICATION) publicclassGreeting {     @PrimaryKey   @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)     private Long id;     @Persistent privateUserauthor;       @Persistent privateStringcontent;     @Persistent private Date date;     publicGreeting(Userauthor, Stringcontent, Date date) {         this.author = author;         this.content = content;         this.date = date;       }       ... }
La Clase de Persistencia Greeting Esta sencilla clase define tres propiedades para un saludo: author, content y date Estos tres campos privados presentan la anotación @Persistent, que indica a DataNucleus que debe almacenarlos como propiedades de objetos en el almacén de datos de AppEngine. La clase también define un campo llamado id, una clave Long que presenta dos anotaciones: @Persistent y @PrimaryKey.  El almacén de datos de AppEngine tiene una noción de las claves de entidades y puede representar las claves de varias formas en un objeto. Más información sobre cómo definir modelos de datos puede encontrarse en: http://code.google.com/intl/es/appengine/docs/java/datastore/dataclasses.html
Serializando datos con JDO Cada solicitud que utiliza el almacén de datos crea una nueva instancia de la clase PersistenceManager que se obtiene a través de PersistenceManagerFactory Una instancia de PersistenceManagerFactory tarda algún tiempo en inicializarse Afortunadamente, sólo se necesita una instancia para cada aplicación Creamos la clase singletonPMF para resolverlo: packageguestbook; importjavax.jdo.JDOHelper; importjavax.jdo.PersistenceManagerFactory; public final class PMF {	 privatestatic final PersistenceManagerFactorypmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");	 private PMF() {}	 publicstaticPersistenceManagerFactoryget() {	returnpmfInstance;	   } } Para usarlo creamos una nueva instancia de Greeting mediante la ejecución del constructor.  Para guardar la instancia en el almacén de datos, crea una clase PersistenceManager a través de PMF.get() e invocamos sobre él makePersistent()
Serializando datos con JDO Dentro del fichero SignGuestBookServlet introduciríamos los siguientes cambios para serializar los saludos en AppEngineDataStore, a través de JDO: Stringcontent = req.getParameter("content");		 Date date = new Date();         Greetinggreeting = new Greeting(user, content, date);		 PersistenceManager pm = PMF.get().getPersistenceManager();		 try {			 pm.makePersistent(greeting);		 } finally {			 pm.close();		 }
Consultando datos con JDO El estándar 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>Theguestbook has no messages.</p> <%		 } else {			 for (Greeting g : greetings) {				 if (g.getAuthor() == null) { %>					       <p>Ananonymouspersonwrote:</p> <%				     } else { %>					       <p><b><%= g.getAuthor().getNickname() %></b> wrote:</p> <%		      } %>				     <blockquote><%= g.getContent() %></blockquote>	<%			   }		 }		 pm.close();		 %>
Usando Ficheros Estáticos Hay muchos casos en los que querrás mostrar los archivos estáticos directamente en el navegador web: imágenes, vídeos Para una mayor eficiencia, AppEngine muestra los archivos estáticos desde servidores independientes en lugar de los que ejecutan servlets. AppEngine considera todos los archivos del directorio WAR como archivos estáticos, salvo JSP y los archivos de WEB-INF/ Cualquier solicitud de una URL cuya ruta coincida con un archivo estático lo muestra  Puedes configurar los archivos que quieres que AppEngine considere como archivos estáticos a través del archivo appengine-web.xml La siguiente página da más información 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; } Añadir a guestbook.jsp lo siguiente:  <head> <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> </head>
Creando de Objetos y Claves Para almacenar un objeto de datos sencillo en el almacén de datos, ejecuta el método makePersistent() del PersistenceManager y transfiérelo 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 más sencillas están basadas en los tipos Long o String, pero también se pueden crear con la clase Key.  importcom.google.appengine.api.datastore.Key; importcom.google.appengine.api.datastore.KeyFactory; // ... Key k = KeyFactory.createKey(Employee.class.getSimpleName(), "Alfred.Smith@example.com"); Para recuperar un elemento por clave podemos usar lo siguiente, se puede pasar como segundo argumento una clave, un entero o un string: Employee e = pm.getObjectById(Employee.class, "Alfred.Smith@example.com");
Actualización y Borrado de Objetos El siguiente código muestra cómo actualizar un objeto persistente: publicvoidupdateEmployeeTitle(Useruser, StringnewTitle) { 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 cómo borrar un objeto: pm.deletePersistent(e);
Realizando Consultas con JDO JDOQL es similar a SQL, aunque es más adecuado para bases de datos relacionadas con objetos, como, por ejemplo, el almacén de datos de AppEngine. Dos usos diferentes: Puedes especificar parte o la totalidad de la consulta mediante métodos de ejecución en el objeto de consulta importjava.util.List; importjavax.jdo.Query; // ... Queryquery = pm.newQuery(Employee.class); query.setFilter("lastName == lastNameParam"); query.setOrdering("hireDatedesc"); query.declareParameters("StringlastNameParam"); try {    List<Employee> results = (List<Employee>) query.execute("Smith"); if (results.iterator().hasNext()) { for (Employee e : results) { 	   // ... 	   } 	} else { 	   // ... no results ... 	} } finally { query.closeAll(); }
Realizando Consultas con JDO Puedes especificar una consulta completa en una cadena mediante la sintaxis de cadena JDOQL: Queryquery = pm.newQuery("selectfromEmployee " +    "wherelastName == lastNameParam " +    "orderbyhireDatedesc " +    "parametersStringlastNameParam"); List<Employee> results = (List<Employee>) query.execute("Smith"); Otro modo: Queryquery = pm.newQuery(Employee.class,    "lastName == lastNameParamorderbyhireDatedesc"); query.declareParameters("StringlastNameParam"); List<Employee> results = (List<Employee>) query.execute("Smith"); Query query = pm.newQuery(Employee.class,    "lastName == 'Smith' order by hireDatedesc");
Filtros y Restricciones en Consultas JDO sobre AppEngine Algunos ejemplos de filtros son: query.setFilter("lastName == 'Smith' && hireDate > hireDateMinimum"); query.declareParameters("Date hireDateMinimum"); Queryquery = pm.newQuery(Employee.class,    "(lastName == 'Smith' || lastName == 'Jones')" +    " && firstName == 'Harold'"); ATENCIÓN: 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 sólo están permitidos en una propiedad
Ejemplo Objeto Serializable La siguiente clase define un objeto que puede serializarse en JDO: importjava.io.Serializable; publicclassDownloadableFileimplementsSerializable{ private byte[] content; privateStringfilename; privateStringmimeType; // ... accessors ... } La siguiente clase define cómo usarlo: importjavax.jdo.annotations.Persistent; importDownloadableFile; // ... @Persistent(serialized = "true"); privateDownloadableFilefile;
Ejemplo Relación 1 a 1 entre Entidades importcom.google.appengine.api.datastore.Key; // ... imports ... @PersistenceCapable publicclassContactInfo {    @PrimaryKey    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key;    @Persistent privateStringstreetAddress;    @Persistent privateStringcity;    @Persistent privateStringstateOrProvince;    @Persistent privateStringzipCode;    // ... accessors ... } importContactInfo; // ... imports ... @PersistenceCapable publicclassEmployee {     @PrimaryKey     @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key;     @Persistent privateContactInfomyContactInfo;     // ... accessors ... }
Relaciones Uno a Varios Ejemplo de relación bidireccional uno a varios: // Employee.java importjava.util.List; // ... @Persistent private List<ContactInfo> contactInfoSets; // ContactInfo.java importEmployee; // ... @Persistent privateEmployeeemployee;
Relaciones Varios a Varios Ejemplo de relación varios a varios, sólo se puede hacer guardando colecciones de claves en ambas relaciones implicadas: //Person.java importjava.util.Set; importcom.google.appengine.api.datastore.Key; // ... @Persistent private Set<Key> favoriteFoods; //Food.java importjava.util.Set; importcom.google.appengine.api.datastore.Key; // ... @Persistent private Set<Key> foodFans; // Album.java // ... publicvoidaddFavoriteFood(Foodfood) {     favoriteFoods.add(food.getKey()); food.getFoodFans().add(getKey()); } publicvoidremoveFavoriteFood(Foodfood) { favoriteFoods.remove(food.getKey()); food.getFoodFans().remove(getKey()); }
Características Avanzadas de Google AppEngine Planificación 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 Envío de mensajes instantáneos con XMPP e email  http://code.google.com/appengine/docs/java/xmpp/overview.html Colas de tareas – permite ejecutar asíncronamente tareas http://code.google.com/appengine/docs/java/taskqueue/overview.html
Planificación de Tareas con Cron El servicio AppEngine Cron Service permite planificar tareas que se ejecutan en un momento o periodos determinados. Los trabajos cron (cron jobs) son ejecutados por AppEngine Cron Service Algunos ejemplos de uso serían: Envío de email con informe diario Actualización de tu caché de datos cada 10 minutos Documentación en: http://code.google.com/appengine/docs/java/config/cron.html Formato de las planificaciones: ("every"|ordinal) (days) ["of" (monthspec)] (time)
Planificación de Tareas con Cron El fichero WEB-INFron.xmlcontrolacronparatuaplicación: <?xmlversion="1.0" encoding="UTF-8"?> <cronentries> <cron>  <url>/recache</url>  <description>Repopulatethe cache every 2 minutes</description>  <schedule>every 2 minutes</schedule></cron><cron>  <url>/weeklyreport</url>  <description>Mail out a weeklyreport</description>  <schedule>everymonday 08:30</schedule>  <timezone>America/New_York</timezone></cron> </cronentries>
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 AppEngine incluye un servicio de memoria caché El API Java de Memcache implementa la interfaz JCache (javax.cache), un estándar 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 cuándo los valores vencen en la memoria caché Inspeccionar el contenido de la memoria caché y obtener estadísticas sobre ella Utilizar "funciones de escucha" para añadir un comportamiento personalizado al establecer y borrar valores.
Pasos para Hacer uso de Memcache Obtención y configuración de una instancia de Cache, para ello hay que configurar los parámetros del método createCache importjavax.cache.Cache; importjavax.cache.CacheException; importjavax.cache.CacheFactory; // ... Cache cache; try { Mapprops = new Map;    props.put(GCacheFactory.EXPIRATION_DELTA, 3600);    props.put(MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT, true); CacheFactorycacheFactory = CacheManager.getInstance().getCacheFactory();    // cache = cacheFactory.createCache(Collections.emptyMap());    cache = cacheFactory.createCache(props); } catch (CacheException e) { // ... } Establecimiento y obtención de valores.   Se comporta como un mapa Puedes almacenar claves y valores a través del método put() y recuperar valores con el método get() Otros métodos de interés son: remove(), clear(), containsKey(), isEmpty() y size() Más documentación en: http://code.google.com/intl/es/appengine/docs/java/memcache/usingjcache.html
URL Fetch Java API GAE permite realizar conexiones HTTP y HTTPS a través 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 página mediante java.net.URL y el método openStream() El método 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 conexión como: Añadir cabeceras: connection.setRequestProperty("X-MyApp-Version", "2.7.3"); Modificar el hecho de que las peticiones se redirijan directamente: connection.setRequestProperty("X-MyApp-Version", "2.7.3"); Más detalles en: http://code.google.com/intl/en/appengine/docs/java/urlfetch/usingjavanet.html
Mail Java API Una aplicación en AppEngine puede enviar mensajes en representación del administrador de la página o de usuarios autorizados con cuentas Google La Mail Service Java API hace uso de javax.mail Se puede configurar tu aplicación para recibir mensajes en una dirección con el formato string@appid.appspotmail.com Cuando una aplicación se ejecuta en el servidor de desarrollo, el mensaje enviado se imprime en el log, no se envía
Enviando un Mensaje ... importjava.util.Properties; importjavax.mail.Message; importjavax.mail.MessagingException; importjavax.mail.Session; importjavax.mail.Transport; importjavax.mail.internet.AddressException; importjavax.mail.internet.InternetAddress; importjavax.mail.internet.MimeMessage; // ...  Propertiesprops = new Properties(); Sessionsession = Session.getDefaultInstance(props, null); StringmsgBody = "...“; try { Messagemsg = 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 beenactivated"); msg.setText(msgBody); Transport.send(msg); } catch (AddressException e) {    // ... } catch (MessagingException e) {    // ... }
Recibiendo un Mensaje Los pasos a seguir son: Configurar tu aplicación para ser receptora de email en la dirección: string@appid.appspotmail.com Modificando el fichero appengine-web.xml:  <inbound-services>    <service>mail</service> </inbound-services> Modificando el fichero web.xml, que recibirá mensajes en la siguiente dirección: /_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>
Recibiendo un Mensaje Los pasos a seguir son: Crear un servlet que reciba los mensajes importjava.io.IOException; importjava.util.Properties;  importjavax.mail.Session;  importjavax.mail.internet.MimeMessage;  importjavax.servlet.http.*;  publicclassMailHandlerServletextendsHttpServlet{ publicvoiddoPost(HttpServletRequestreq,  HttpServletResponseresp) throwsIOException {  Propertiesprops = new Properties();  Sessionsession = Session.getDefaultInstance(props, null); MimeMessagemessage = new MimeMessage(session, req.getInputStream());       … }
TaskQueue API Una aplicación Java puede crear una cola configurada en el fichero de configuración WEB-INF/queue.xml  Para encolar una tarea, hay que obtener una instancia de Queue usando una QueueFactory y luego invocar el método add() Puedes obtener una cola por nombre declarada en el fichero queue.xml o la cola por defecto con el método getDefaultQueue() Se puede añadir una tarea a la cola pasando una instancia de TaskOptions al método add() Se invocará un servlet que será quien ejecute la tarea encolada (ver ejemplo siguiente trasparencia) Espacio de nombres en versión beta: com.google.appengine.api.labs.taskqueue
Ejemplo de TaskQueue API El siguiente ejemplo muestra cómo añadir una tarea a una cola: importcom.google.appengine.api.labs.taskqueue.Queue; importcom.google.appengine.api.labs.taskqueue.QueueFactory; importstaticcom.google.appengine.api.labs.taskqueue.TaskOptions.Builder.*; // ... Queuequeue = QueueFactory.getDefaultQueue(); queue.add(url("/worker").param("key", key));
Ejemplo de TaskQueue API Ejemplo de queue.xml, donde s indica segundos, m minutos, h horas y d días, es decir, la frecuencia con la que las tareas encoladas serían procesadas: <queue-entries>  <queue>    <name>default</name>    <rate>1/s</rate>  </queue>  <queue>    <name>mail-queue</name>    <rate>2000/d</rate>    <bucket-size>10</bucket-size>  </queue>  <queue>    <name>background-processing</name>    <rate>5/s</rate>  </queue></queue-entries>
Combinando Struts2 y GAE Revisar ejemplo: struts2tutorial Modificaciones a realizar en la distribución de struts2tutorial: Reimplementar la clase freemarker.core.TextBlock Inicializar a null el SecurityManager de OgnlRuntime Explicación de cómo hacerlo en:  http://whyjava.wordpress.com/2009/08/30/creating-struts2-application-on-google-app-engine-gae/
Pluginfor 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/
Importación y Exportación de Datos Se pueden acceder a datos detrás de tu Intranet desde una aplicación de Google AppEngine, 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/uploadingdata.html
Google AppEnginefor Business Las aplicaciones generadas con AppEnginefor Business usan las APIs de Java y Python, pero permiten acceder al desarrollador a capacidades especiales (premium): Acceso a SSL y SQL Tendrán un coste adicional Mas información en: http://code.google.com/appengine/business/
Limitaciones Google AppEngine El servicio tiene varias limitaciones: Solo hasta recientemente no todo el mundo podía acceder a él Es gratis durante el periodo de pruebas, pero con límites de uso: 500 MB de almacenamiento, 200 millones de megaciclos/día 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 técnicas originales parcialmente resueltas: Los desarrolladores solamente tienen acceso de lectura al sistema de ficheros de AppEngine Solamente se puede ejecutar código a partir de una petición HTTP Solamente se puede subir código 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á detrás de Google AppEngine
Google App Engine vs. Amazon Web Services A primera vista Google AppEngine es un competidor a la suite de servicios web ofrecida por Amazon: S3 para almacenamiento EC2 para la creación de servidores virtuales SimpleDB como base de datos Pero … Google AppEngine es una plataforma mucho más 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)
Google App Engine vs. Amazon Web Services
Referencias Google AppEngine http://code.google.com/appengine/

Weitere ähnliche Inhalte

Was ist angesagt?

Software Empotrado
Software EmpotradoSoftware Empotrado
Software Empotradochivivi
 
Topicos Avanzados de Programacion - Unidad 3 componentes y librerias
Topicos Avanzados de Programacion - Unidad 3 componentes y libreriasTopicos Avanzados de Programacion - Unidad 3 componentes y librerias
Topicos Avanzados de Programacion - Unidad 3 componentes y libreriasJosé Antonio Sandoval Acosta
 
Diagrama Despliegue
Diagrama DespliegueDiagrama Despliegue
Diagrama Desplieguemireya2022
 
Patrones de diseño(presentación 7)
Patrones de diseño(presentación 7)Patrones de diseño(presentación 7)
Patrones de diseño(presentación 7)programadorjavablog
 
Diagrama de clases
Diagrama de clasesDiagrama de clases
Diagrama de clasesjmachado614
 
Modelamiento De Negocio
Modelamiento De NegocioModelamiento De Negocio
Modelamiento De NegocioKudos S.A.S
 
Ingeniería de requisitos e ingeniería de requerimientos
Ingeniería de requisitos e ingeniería de requerimientosIngeniería de requisitos e ingeniería de requerimientos
Ingeniería de requisitos e ingeniería de requerimientosCesar Prado
 
Elementos orientados al flujo
Elementos orientados al flujoElementos orientados al flujo
Elementos orientados al flujoAlumic S.A
 
Unidad 1 Ingenieria de software
Unidad 1 Ingenieria de softwareUnidad 1 Ingenieria de software
Unidad 1 Ingenieria de softwareJahiro Bojorquez
 
Unidad 3 gestion de procesos en linux
Unidad 3 gestion de procesos en linuxUnidad 3 gestion de procesos en linux
Unidad 3 gestion de procesos en linuxjcfarit
 
SISTEMAS OPERATIVOS MULTIMEDIA
SISTEMAS OPERATIVOS MULTIMEDIASISTEMAS OPERATIVOS MULTIMEDIA
SISTEMAS OPERATIVOS MULTIMEDIAMari Ng
 
Administración de procesos y del procesador
Administración de procesos y del procesadorAdministración de procesos y del procesador
Administración de procesos y del procesadorFernando Camacho
 

Was ist angesagt? (20)

Software Empotrado
Software EmpotradoSoftware Empotrado
Software Empotrado
 
Topicos Avanzados de Programacion - Unidad 3 componentes y librerias
Topicos Avanzados de Programacion - Unidad 3 componentes y libreriasTopicos Avanzados de Programacion - Unidad 3 componentes y librerias
Topicos Avanzados de Programacion - Unidad 3 componentes y librerias
 
Metodologia msf
Metodologia msfMetodologia msf
Metodologia msf
 
Diagrama Despliegue
Diagrama DespliegueDiagrama Despliegue
Diagrama Despliegue
 
Patrones de diseño(presentación 7)
Patrones de diseño(presentación 7)Patrones de diseño(presentación 7)
Patrones de diseño(presentación 7)
 
Casos De Uso
Casos De UsoCasos De Uso
Casos De Uso
 
Diagrama de clases
Diagrama de clasesDiagrama de clases
Diagrama de clases
 
Hilos en solaris.
Hilos en solaris.Hilos en solaris.
Hilos en solaris.
 
Modelamiento De Negocio
Modelamiento De NegocioModelamiento De Negocio
Modelamiento De Negocio
 
Ingeniería de requisitos e ingeniería de requerimientos
Ingeniería de requisitos e ingeniería de requerimientosIngeniería de requisitos e ingeniería de requerimientos
Ingeniería de requisitos e ingeniería de requerimientos
 
Modelos concurrentes
Modelos concurrentesModelos concurrentes
Modelos concurrentes
 
Elementos orientados al flujo
Elementos orientados al flujoElementos orientados al flujo
Elementos orientados al flujo
 
Unidad 1 Ingenieria de software
Unidad 1 Ingenieria de softwareUnidad 1 Ingenieria de software
Unidad 1 Ingenieria de software
 
Computo en paralelo con OpenMP y OpenMPI
Computo en paralelo con OpenMP y OpenMPIComputo en paralelo con OpenMP y OpenMPI
Computo en paralelo con OpenMP y OpenMPI
 
Unidad 3 gestion de procesos en linux
Unidad 3 gestion de procesos en linuxUnidad 3 gestion de procesos en linux
Unidad 3 gestion de procesos en linux
 
SISTEMAS OPERATIVOS MULTIMEDIA
SISTEMAS OPERATIVOS MULTIMEDIASISTEMAS OPERATIVOS MULTIMEDIA
SISTEMAS OPERATIVOS MULTIMEDIA
 
Administración de procesos y del procesador
Administración de procesos y del procesadorAdministración de procesos y del procesador
Administración de procesos y del procesador
 
Socket
SocketSocket
Socket
 
DIAGRAMAS DE CLASE
DIAGRAMAS DE CLASEDIAGRAMAS DE CLASE
DIAGRAMAS DE CLASE
 
HA2NV50 EQ8-StarUML
HA2NV50 EQ8-StarUMLHA2NV50 EQ8-StarUML
HA2NV50 EQ8-StarUML
 

Andere mochten auch

Google Cloud Platform y Python
Google Cloud Platform y PythonGoogle Cloud Platform y Python
Google Cloud Platform y PythonCarlos Toxtli
 
Search Engine Optimization (SEO)
Search Engine Optimization (SEO)Search Engine Optimization (SEO)
Search Engine Optimization (SEO)Dennis Deacon
 
Periodic Table of SEO Success Factors & Guide to SEO by SearchEngineLand
Periodic Table of SEO Success Factors & Guide to SEO by SearchEngineLandPeriodic Table of SEO Success Factors & Guide to SEO by SearchEngineLand
Periodic Table of SEO Success Factors & Guide to SEO by SearchEngineLandSearch Engine Land
 
Internal Combustion Engines - Construction and Working (All you need to know,...
Internal Combustion Engines - Construction and Working (All you need to know,...Internal Combustion Engines - Construction and Working (All you need to know,...
Internal Combustion Engines - Construction and Working (All you need to know,...Mihir Pai
 
Tk03 Google App Engine Fr
Tk03 Google App Engine FrTk03 Google App Engine Fr
Tk03 Google App Engine FrValtech
 
ppt on 2 stroke and 4 stroke petrol engine
ppt on 2 stroke and 4 stroke petrol engineppt on 2 stroke and 4 stroke petrol engine
ppt on 2 stroke and 4 stroke petrol engineharshid panchal
 
DNUG2015 Frühjahrskonferenz: Brücken bauen, Grenzen überwinden: Domino im Dia...
DNUG2015 Frühjahrskonferenz: Brücken bauen, Grenzen überwinden: Domino im Dia...DNUG2015 Frühjahrskonferenz: Brücken bauen, Grenzen überwinden: Domino im Dia...
DNUG2015 Frühjahrskonferenz: Brücken bauen, Grenzen überwinden: Domino im Dia...JRibbeck
 
I.C.ENGINE PPT
I.C.ENGINE PPTI.C.ENGINE PPT
I.C.ENGINE PPT8695
 
CAP 4: SEO - Optimizacion de Contenido
CAP 4: SEO - Optimizacion de ContenidoCAP 4: SEO - Optimizacion de Contenido
CAP 4: SEO - Optimizacion de ContenidoGary Briceño
 
App engine
App engineApp engine
App engineThirdWay
 
CAP 3: SEO - Keywords Research
CAP 3: SEO - Keywords ResearchCAP 3: SEO - Keywords Research
CAP 3: SEO - Keywords ResearchGary Briceño
 
Desarrollando para Nmap Scripting Engine (NSE) [GuadalajaraCON 2013]
Desarrollando para Nmap Scripting Engine (NSE) [GuadalajaraCON 2013]Desarrollando para Nmap Scripting Engine (NSE) [GuadalajaraCON 2013]
Desarrollando para Nmap Scripting Engine (NSE) [GuadalajaraCON 2013]Websec México, S.C.
 
Presentacion introduccion ibm file net p8 v10
Presentacion introduccion ibm file net p8 v10Presentacion introduccion ibm file net p8 v10
Presentacion introduccion ibm file net p8 v10Javier Laguens Garcia
 

Andere mochten auch (20)

Curso Cloud Computing, Parte 1: Amazon Web Services
Curso Cloud Computing, Parte 1: Amazon Web ServicesCurso Cloud Computing, Parte 1: Amazon Web Services
Curso Cloud Computing, Parte 1: Amazon Web Services
 
Google Cloud Platform y Python
Google Cloud Platform y PythonGoogle Cloud Platform y Python
Google Cloud Platform y Python
 
Understanding the Diesel Engine
Understanding the Diesel EngineUnderstanding the Diesel Engine
Understanding the Diesel Engine
 
RoomCloud Booking Engine
RoomCloud Booking EngineRoomCloud Booking Engine
RoomCloud Booking Engine
 
Search Engine Optimization (SEO)
Search Engine Optimization (SEO)Search Engine Optimization (SEO)
Search Engine Optimization (SEO)
 
Periodic Table of SEO Success Factors & Guide to SEO by SearchEngineLand
Periodic Table of SEO Success Factors & Guide to SEO by SearchEngineLandPeriodic Table of SEO Success Factors & Guide to SEO by SearchEngineLand
Periodic Table of SEO Success Factors & Guide to SEO by SearchEngineLand
 
Ic engine
Ic engineIc engine
Ic engine
 
Internal Combustion Engines - Construction and Working (All you need to know,...
Internal Combustion Engines - Construction and Working (All you need to know,...Internal Combustion Engines - Construction and Working (All you need to know,...
Internal Combustion Engines - Construction and Working (All you need to know,...
 
Tk03 Google App Engine Fr
Tk03 Google App Engine FrTk03 Google App Engine Fr
Tk03 Google App Engine Fr
 
ppt on 2 stroke and 4 stroke petrol engine
ppt on 2 stroke and 4 stroke petrol engineppt on 2 stroke and 4 stroke petrol engine
ppt on 2 stroke and 4 stroke petrol engine
 
DNUG2015 Frühjahrskonferenz: Brücken bauen, Grenzen überwinden: Domino im Dia...
DNUG2015 Frühjahrskonferenz: Brücken bauen, Grenzen überwinden: Domino im Dia...DNUG2015 Frühjahrskonferenz: Brücken bauen, Grenzen überwinden: Domino im Dia...
DNUG2015 Frühjahrskonferenz: Brücken bauen, Grenzen überwinden: Domino im Dia...
 
I.C.ENGINE PPT
I.C.ENGINE PPTI.C.ENGINE PPT
I.C.ENGINE PPT
 
Google App Engine - INTRO
Google App Engine - INTROGoogle App Engine - INTRO
Google App Engine - INTRO
 
CAP 4: SEO - Optimizacion de Contenido
CAP 4: SEO - Optimizacion de ContenidoCAP 4: SEO - Optimizacion de Contenido
CAP 4: SEO - Optimizacion de Contenido
 
App engine
App engineApp engine
App engine
 
CAP 3: SEO - Keywords Research
CAP 3: SEO - Keywords ResearchCAP 3: SEO - Keywords Research
CAP 3: SEO - Keywords Research
 
El SEOy la geolocalización
El SEOy la geolocalizaciónEl SEOy la geolocalización
El SEOy la geolocalización
 
Jet engines
Jet enginesJet engines
Jet engines
 
Desarrollando para Nmap Scripting Engine (NSE) [GuadalajaraCON 2013]
Desarrollando para Nmap Scripting Engine (NSE) [GuadalajaraCON 2013]Desarrollando para Nmap Scripting Engine (NSE) [GuadalajaraCON 2013]
Desarrollando para Nmap Scripting Engine (NSE) [GuadalajaraCON 2013]
 
Presentacion introduccion ibm file net p8 v10
Presentacion introduccion ibm file net p8 v10Presentacion introduccion ibm file net p8 v10
Presentacion introduccion ibm file net p8 v10
 

Ähnlich wie Curso Cloud Computing, Parte 2: Google App Engine

Mi primera App con GAE
Mi primera App con GAEMi primera App con GAE
Mi primera App con GAEGDG Lima
 
Appcircus Academy: Integración de Social Media en Android
Appcircus Academy: Integración de Social Media en AndroidAppcircus Academy: Integración de Social Media en Android
Appcircus Academy: Integración de Social Media en AndroidAlberto Ruibal
 
Mi primera app con GAE y GWT
Mi primera app con GAE y GWTMi primera app con GAE y GWT
Mi primera app con GAE y GWTGDG Lima
 
Taller de introducción a Google App Engine
Taller de introducción a Google App EngineTaller de introducción a Google App Engine
Taller de introducción a Google App EngineManuel Martín
 
Congreso visión 2012 - taller introducción app engine
Congreso visión 2012 - taller introducción app engineCongreso visión 2012 - taller introducción app engine
Congreso visión 2012 - taller introducción app engineNigeŗ Arce
 
Django - Plataforma de sitios web
Django - Plataforma de sitios webDjango - Plataforma de sitios web
Django - Plataforma de sitios webjcarazo
 
Neo Humano - GTUG Labs (12-12-2009)
Neo Humano - GTUG Labs (12-12-2009)Neo Humano - GTUG Labs (12-12-2009)
Neo Humano - GTUG Labs (12-12-2009)Neo Humano
 
LabAndroid: Taller "Mi Primera Aplicación Android"
LabAndroid: Taller "Mi Primera Aplicación Android"LabAndroid: Taller "Mi Primera Aplicación Android"
LabAndroid: Taller "Mi Primera Aplicación Android"Alberto Ruibal
 
MobileCONGalicia Introducción a Android
MobileCONGalicia Introducción a AndroidMobileCONGalicia Introducción a Android
MobileCONGalicia Introducción a AndroidAlberto Ruibal
 
Servicio web
Servicio web Servicio web
Servicio web Yael67
 
Proyect Evenge. Event manager
Proyect Evenge. Event managerProyect Evenge. Event manager
Proyect Evenge. Event managerIvan Ortega
 
Introducción a Android y conexión con SharePoint
Introducción a Android y conexión con SharePointIntroducción a Android y conexión con SharePoint
Introducción a Android y conexión con SharePointAlbert Lozano Ciller
 
Taller de introducción al desarrollo web con Django
Taller de introducción al desarrollo web con DjangoTaller de introducción al desarrollo web con Django
Taller de introducción al desarrollo web con DjangoJuan Rodríguez
 

Ähnlich wie Curso Cloud Computing, Parte 2: Google App Engine (20)

Python Gae django
Python Gae djangoPython Gae django
Python Gae django
 
Mi primera App con GAE
Mi primera App con GAEMi primera App con GAE
Mi primera App con GAE
 
Appcircus Academy: Integración de Social Media en Android
Appcircus Academy: Integración de Social Media en AndroidAppcircus Academy: Integración de Social Media en Android
Appcircus Academy: Integración de Social Media en Android
 
Google apps engine
Google apps engineGoogle apps engine
Google apps engine
 
Servicios web
Servicios webServicios web
Servicios web
 
Mi primera app con GAE y GWT
Mi primera app con GAE y GWTMi primera app con GAE y GWT
Mi primera app con GAE y GWT
 
Taller de introducción a Google App Engine
Taller de introducción a Google App EngineTaller de introducción a Google App Engine
Taller de introducción a Google App Engine
 
Congreso visión 2012 - taller introducción app engine
Congreso visión 2012 - taller introducción app engineCongreso visión 2012 - taller introducción app engine
Congreso visión 2012 - taller introducción app engine
 
Welcome to Django
Welcome to DjangoWelcome to Django
Welcome to Django
 
Servicio web.lauraivettecolinvillarreal
Servicio web.lauraivettecolinvillarrealServicio web.lauraivettecolinvillarreal
Servicio web.lauraivettecolinvillarreal
 
Google Api
Google ApiGoogle Api
Google Api
 
Django - Plataforma de sitios web
Django - Plataforma de sitios webDjango - Plataforma de sitios web
Django - Plataforma de sitios web
 
Neo Humano - GTUG Labs (12-12-2009)
Neo Humano - GTUG Labs (12-12-2009)Neo Humano - GTUG Labs (12-12-2009)
Neo Humano - GTUG Labs (12-12-2009)
 
LabAndroid: Taller "Mi Primera Aplicación Android"
LabAndroid: Taller "Mi Primera Aplicación Android"LabAndroid: Taller "Mi Primera Aplicación Android"
LabAndroid: Taller "Mi Primera Aplicación Android"
 
MobileCONGalicia Introducción a Android
MobileCONGalicia Introducción a AndroidMobileCONGalicia Introducción a Android
MobileCONGalicia Introducción a Android
 
Servicio web
Servicio web Servicio web
Servicio web
 
RAML
RAMLRAML
RAML
 
Proyect Evenge. Event manager
Proyect Evenge. Event managerProyect Evenge. Event manager
Proyect Evenge. Event manager
 
Introducción a Android y conexión con SharePoint
Introducción a Android y conexión con SharePointIntroducción a Android y conexión con SharePoint
Introducción a Android y conexión con SharePoint
 
Taller de introducción al desarrollo web con Django
Taller de introducción al desarrollo web con DjangoTaller de introducción al desarrollo web con Django
Taller de introducción al desarrollo web con Django
 

Mehr von Diego López-de-Ipiña González-de-Artaza

Humanized Computing: the path towards higher collaboration and reciprocal lea...
Humanized Computing: the path towards higher collaboration and reciprocal lea...Humanized Computing: the path towards higher collaboration and reciprocal lea...
Humanized Computing: the path towards higher collaboration and reciprocal lea...Diego López-de-Ipiña González-de-Artaza
 
Ontological Infrastructure for Interoperable Research Information Systems: HE...
Ontological Infrastructure for Interoperable Research Information Systems: HE...Ontological Infrastructure for Interoperable Research Information Systems: HE...
Ontological Infrastructure for Interoperable Research Information Systems: HE...Diego López-de-Ipiña González-de-Artaza
 
Fostering multi-stakeholder collaboration through co-production and rewarding
Fostering multi-stakeholder collaboration through co-production and rewarding Fostering multi-stakeholder collaboration through co-production and rewarding
Fostering multi-stakeholder collaboration through co-production and rewarding Diego López-de-Ipiña González-de-Artaza
 
A Collaborative Environment to Boost Sustainable Engaged Research & Co-Produc...
A Collaborative Environment to Boost Sustainable Engaged Research & Co-Produc...A Collaborative Environment to Boost Sustainable Engaged Research & Co-Produc...
A Collaborative Environment to Boost Sustainable Engaged Research & Co-Produc...Diego López-de-Ipiña González-de-Artaza
 
A Collaborative Environment to Boost Co-Production of Sustainable Public Serv...
A Collaborative Environment to Boost Co-Production of Sustainable Public Serv...A Collaborative Environment to Boost Co-Production of Sustainable Public Serv...
A Collaborative Environment to Boost Co-Production of Sustainable Public Serv...Diego López-de-Ipiña González-de-Artaza
 
Social Coin: Blockchain-mediated incentivization of citizens for sustainable ...
Social Coin: Blockchain-mediated incentivization of citizens for sustainable ...Social Coin: Blockchain-mediated incentivization of citizens for sustainable ...
Social Coin: Blockchain-mediated incentivization of citizens for sustainable ...Diego López-de-Ipiña González-de-Artaza
 
Human-centric Collaborative Services : IoT, Broad Data, Crowdsourcing, Engage...
Human-centric Collaborative Services : IoT, Broad Data, Crowdsourcing, Engage...Human-centric Collaborative Services : IoT, Broad Data, Crowdsourcing, Engage...
Human-centric Collaborative Services : IoT, Broad Data, Crowdsourcing, Engage...Diego López-de-Ipiña González-de-Artaza
 
Transiting to SMART COMMUNITIES by fostering Collaboration & CO-CREATION for ...
Transiting to SMART COMMUNITIES by fostering Collaboration & CO-CREATION for ...Transiting to SMART COMMUNITIES by fostering Collaboration & CO-CREATION for ...
Transiting to SMART COMMUNITIES by fostering Collaboration & CO-CREATION for ...Diego López-de-Ipiña González-de-Artaza
 
ROH: Proceso de Ingeniería Ontológica & Uso y Extensión de Vocabularios Estándar
ROH: Proceso de Ingeniería Ontológica & Uso y Extensión de Vocabularios EstándarROH: Proceso de Ingeniería Ontológica & Uso y Extensión de Vocabularios Estándar
ROH: Proceso de Ingeniería Ontológica & Uso y Extensión de Vocabularios EstándarDiego López-de-Ipiña González-de-Artaza
 

Mehr von Diego López-de-Ipiña González-de-Artaza (20)

Humanized Computing: the path towards higher collaboration and reciprocal lea...
Humanized Computing: the path towards higher collaboration and reciprocal lea...Humanized Computing: the path towards higher collaboration and reciprocal lea...
Humanized Computing: the path towards higher collaboration and reciprocal lea...
 
Generative AI How It's Changing Our World and What It Means for You_final.pdf
Generative AI How It's Changing Our World and What It Means for You_final.pdfGenerative AI How It's Changing Our World and What It Means for You_final.pdf
Generative AI How It's Changing Our World and What It Means for You_final.pdf
 
Democratizing Co-Production Of Sustainable Public Services
Democratizing Co-Production Of Sustainable Public Services Democratizing Co-Production Of Sustainable Public Services
Democratizing Co-Production Of Sustainable Public Services
 
Ontological Infrastructure for Interoperable Research Information Systems: HE...
Ontological Infrastructure for Interoperable Research Information Systems: HE...Ontological Infrastructure for Interoperable Research Information Systems: HE...
Ontological Infrastructure for Interoperable Research Information Systems: HE...
 
Fostering multi-stakeholder collaboration through co-production and rewarding
Fostering multi-stakeholder collaboration through co-production and rewarding Fostering multi-stakeholder collaboration through co-production and rewarding
Fostering multi-stakeholder collaboration through co-production and rewarding
 
A Collaborative Environment to Boost Sustainable Engaged Research & Co-Produc...
A Collaborative Environment to Boost Sustainable Engaged Research & Co-Produc...A Collaborative Environment to Boost Sustainable Engaged Research & Co-Produc...
A Collaborative Environment to Boost Sustainable Engaged Research & Co-Produc...
 
A Collaborative Environment to Boost Co-Production of Sustainable Public Serv...
A Collaborative Environment to Boost Co-Production of Sustainable Public Serv...A Collaborative Environment to Boost Co-Production of Sustainable Public Serv...
A Collaborative Environment to Boost Co-Production of Sustainable Public Serv...
 
PrácticaParticipación-INTERLINK-realizingcoproduction_final.pdf
PrácticaParticipación-INTERLINK-realizingcoproduction_final.pdfPrácticaParticipación-INTERLINK-realizingcoproduction_final.pdf
PrácticaParticipación-INTERLINK-realizingcoproduction_final.pdf
 
INTERLINK: Engaged Research through co-production
INTERLINK: Engaged Research through co-production INTERLINK: Engaged Research through co-production
INTERLINK: Engaged Research through co-production
 
Internet of People: towards a Human-centric computing for Social Good
Internet of People: towards a Human-centric computing for Social GoodInternet of People: towards a Human-centric computing for Social Good
Internet of People: towards a Human-centric computing for Social Good
 
Boosting data-driven innovation in Europe with the support of DIHs
Boosting data-driven innovation in Europe with the support of DIHs Boosting data-driven innovation in Europe with the support of DIHs
Boosting data-driven innovation in Europe with the support of DIHs
 
Social Coin: Blockchain-mediated incentivization of citizens for sustainable ...
Social Coin: Blockchain-mediated incentivization of citizens for sustainable ...Social Coin: Blockchain-mediated incentivization of citizens for sustainable ...
Social Coin: Blockchain-mediated incentivization of citizens for sustainable ...
 
Human-centric Collaborative Services : IoT, Broad Data, Crowdsourcing, Engage...
Human-centric Collaborative Services : IoT, Broad Data, Crowdsourcing, Engage...Human-centric Collaborative Services : IoT, Broad Data, Crowdsourcing, Engage...
Human-centric Collaborative Services : IoT, Broad Data, Crowdsourcing, Engage...
 
Role of Data Incubators shaping European Data Spaces: EDI & REACH cases
Role of Data Incubators shaping European Data Spaces: EDI & REACH casesRole of Data Incubators shaping European Data Spaces: EDI & REACH cases
Role of Data Incubators shaping European Data Spaces: EDI & REACH cases
 
Transiting to SMART COMMUNITIES by fostering Collaboration & CO-CREATION for ...
Transiting to SMART COMMUNITIES by fostering Collaboration & CO-CREATION for ...Transiting to SMART COMMUNITIES by fostering Collaboration & CO-CREATION for ...
Transiting to SMART COMMUNITIES by fostering Collaboration & CO-CREATION for ...
 
ROH: Proceso de Ingeniería Ontológica & Uso y Extensión de Vocabularios Estándar
ROH: Proceso de Ingeniería Ontológica & Uso y Extensión de Vocabularios EstándarROH: Proceso de Ingeniería Ontológica & Uso y Extensión de Vocabularios Estándar
ROH: Proceso de Ingeniería Ontológica & Uso y Extensión de Vocabularios Estándar
 
Introduction to FAIR Data and Research Objects
Introduction to FAIR Data and Research ObjectsIntroduction to FAIR Data and Research Objects
Introduction to FAIR Data and Research Objects
 
Introducción a Linked Open Data (espacios enlazados y enlazables)
Introducción a Linked Open Data (espacios enlazados y enlazables)Introducción a Linked Open Data (espacios enlazados y enlazables)
Introducción a Linked Open Data (espacios enlazados y enlazables)
 
Red Ontologías Hércules – ROH
Red Ontologías Hércules – ROHRed Ontologías Hércules – ROH
Red Ontologías Hércules – ROH
 
Internet de las cosas y datos de ciencia ciudadana para uso público
Internet de las cosas y datos de ciencia ciudadana para uso públicoInternet de las cosas y datos de ciencia ciudadana para uso público
Internet de las cosas y datos de ciencia ciudadana para uso público
 

Kürzlich hochgeladen

EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptxEVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptxJorgeParada26
 
Modulo-Mini Cargador.................pdf
Modulo-Mini Cargador.................pdfModulo-Mini Cargador.................pdf
Modulo-Mini Cargador.................pdfAnnimoUno1
 
Avances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanaAvances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanamcerpam
 
Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21mariacbr99
 
How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.FlorenciaCattelani
 
pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITMaricarmen Sánchez Ruiz
 
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...JohnRamos830530
 
Avances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estosAvances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estossgonzalezp1
 
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxPROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxAlan779941
 
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptxEL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptxMiguelAtencio10
 
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdf
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdfRefrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdf
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdfvladimiroflores1
 

Kürzlich hochgeladen (11)

EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptxEVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
 
Modulo-Mini Cargador.................pdf
Modulo-Mini Cargador.................pdfModulo-Mini Cargador.................pdf
Modulo-Mini Cargador.................pdf
 
Avances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanaAvances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvana
 
Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21
 
How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.
 
pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNIT
 
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
 
Avances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estosAvances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estos
 
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxPROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
 
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptxEL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
 
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdf
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdfRefrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdf
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdf
 

Curso Cloud Computing, Parte 2: Google App Engine

  • 1. Cloud Computing: Google App Engine31 de Mayo de 2011, 18:00-21:00 Dr. Diego Lz. de Ipiña Glz. de Artazadipina@deusto.eshttp://paginaspersonales.deusto.es/dipinahttp://www.slideshare.net/dipinahttp://www.morelab.deusto.es
  • 2. Agenda Ejemplo de PaaS: Google AppEngine (180’) Introducción (15’) DataStore API y GQL (25’) Memcache y Cron (20’) Versiones Python y Java de Google AppEngine(60’) Desarrollo de una aplicación de ejemplo sobre GoogleApp (60’)
  • 3. Google AppEngine 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.
  • 4. Ejemplo Plataforma Cloud: Google App Engine Google AppEngine es una herramienta para el alojamiento de aplicaciones web escalables sobre la infraestructura de Google Su misión es permitir al desarrollador web crear fácilmente aplicaciones web escalables sin ser un experto en sistemas Aporta las siguientes características a los desarrolladores: Limita la responsabilidad del programador al desarrollo y primer despliegue – Google AppEngine provee recursos computacionales dinámicamente según son necesarios Toma control de los picos de tráfico – si nuestro portal crece en popularidad no es necesario actualizar nuestra infraestructura (servidores, BBDD) Ofrece replicación y balanceo de carga automática apoyado en componentes como Bigtable Fácilmente integrable con otros servicios de Google – los desarrolladores pueden hacer uso de componentes existentes y la librería de APIs de Google (email, autenticación, pagos, etc.)
  • 5. Google AppEngine:Características Ofrece una plataforma completa para el alojamiento y escalado automático 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 código Python o Java compilado a Google, lanzar la aplicación y monitorizar el uso y otras métricas Google AppEngine incluye la librería estándar 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 http://code.google.com/intl/en/appengine/docs/
  • 6.
  • 7. Página de presupuestado y facturación de recursos: http://code.google.com/intl/es/appengine/docs/billing.html
  • 8.
  • 9. Google AppEngine: Python y Java Vamos a revisar primero (brevemente) cómo realizar aplicaciones con Python Luego nos centraremos en cómo hacerlo desde Java en mayor grado de detalle
  • 10. GAE forPython: Instalación Descargar Google AppEngine 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 aplicación a App Engine Herramienta de descarga de datos – esunaherramientasencillaquetepermitesubirdatos en ficheros CSV al almacen de datos de appengine http://code.google.com/intl/es/appengine/docs/python/tools/uploadingdata.html
  • 11. Principios Una aplicación de AppEngine se comunica con el servidor que la aloja a través de CGI Cuando recibe una petición el servidor lee de la entrada estándar y de las variables de entorno Cuando genera una respuesta escribe a la salida estándar
  • 12.
  • 13. Ejecutando Hola Mundo en Google App Engine
  • 14. Opciones Avanzadas para GAE forPython Framework webapp que soporta el estándar WSGI Acceso a datos de usuarios mediante la Users API DataStore API Plantillas en Google AppEngine
  • 15. Usando el Almacén de Datos de Google AppEngine Guardar datos en una aplicación web escalable puede ser difícil La infraestructura de AppEngine se encarga de la distribución, replicación y balanceo de carga de los datos detrás de una API sencilla que también 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 detrás. No esrelacional, todaslasentidades de un mismotipotienenlasmismaspropiedades Unapropiedadpuedeteneruno o variosvalores El siguiente import nos da acceso a la base de datos de Google AppEngine: fromgoogle.appengine.extimportdb Para más detalles sobre el DataStore API ir a: http://code.google.com/appengine/docs/datastore/
  • 16. 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. fromgoogle.appengine.extimportdbfromgoogle.appengine.apiimportusersclassPet(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 = 24pet.put()
  • 17. GQL Query Language Para limpiar la base de datos creada: dev_appserver.py --clear_datastorehelloworld/ Ejemplo GQL: ifusers.get_current_user(): user_pets = db.GqlQuery("SELECT * FROM Pet WHERE pet.owner = :1“, users.get_current_user()) forpet in user_pets: pet.spayed_or_neutered = True db.put(user_pets)
  • 18. Usando plantillas en Google App Engine Empotrar HTML en código es algo lioso y difícil de mantener. Los sistemas de plantillas están diseñados para mantener HTML aparte en otro fichero donde elementos con sintaxis especial indican dónde deberían aparecer los datos de la aplicación Dentro de AppEngine puede utilizarse cualquier motor de plantillas empaquetándolo con el código de tu aplicación, 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 fromgoogle.appengine.ext.webappimporttemplate Además reemplazar las sentenciasself.response.out.write por la sentencia template.render(path, template_values), quetomacomoparámetros de entrada: El camino al fichero de la plantilla Un diccionario de valores Y retorna: El texto a renderizar
  • 22. Registrando la aplicación en appengine.google.com
  • 24. Subiendo la aplicación Es necesario realizar los siguientes pasos: Editar el fichero app.yaml file y cambiar el valor de la aplicación: de helloworld al nombre de id de aplicación (enpresadigitala) Ejecutar el siguiente comando: appcfg.py updatehelloworld/ Acceder a la aplicación en http://application-id.appspot.com, por ejemplo en http://enpresadigitala.appspot.com/
  • 26. Accediendo a la aplicación
  • 27. Programando Google App Engine con Django Google AppEngine y Django tienen la habilidad de usar el estándar WSGI para ejecutar aplicaciones Como consecuencia podemos utilizar la pila de Django en Google AppEngine, 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 AppEngine Como ambas APIs son muy similares, tenemos la misma flexibilidad usando la potencia de BigTable, es trivial adaptar un modelo Django a Google AppEngine Además como Google AppEngine ya incluye Django, solamente hay que importar los módulos que utilizarías normalmente Para usar el gestor WSGI tenemos que realizar los siguientes pasos: Importar util de google.appengine.ext.webapp Importar WSGI handler de Django [OPCIONAL] Redirigir los logs a la AdminConsole de Google AppEngine Es conveniente cambiar las siguientes configuraciones en Django: Dejar vacías las variables DATABASE_* de settings.py Deshabilitar el middleware de session y autenticación que hace uso de los modelos Django Más info en: http://code.google.com/appengine/articles/django.html Revisar ejemplo de encuestas programado en Django para AppEngine en: examples/googleappengine/python/djangosolopsiteappengine
  • 28. Ejemplo Django Compleja sobre AppEngine
  • 29. AppEngine para Java Crea aplicaciones web a través de tecnologías estándar de Java y las ejecuta en la infraestructura escalable Google Usa JVM Java 6, interfaz de servlets Java y la compatibilidad de interfaces estándar como JDO, JPA, JavaMail y JCache AppEngine utiliza el estándar Java Servlet para aplicaciones web JVM se ejecuta en un entorno seguro de la "zona de pruebas" para aislar tu aplicación por servicio y seguridad. Una aplicación en GAE sólo pueda realizar acciones que no interfieran con el rendimiento ni con la escalabilidad de otras aplicaciones. 
  • 30. Funcionalidad de AppEnginefor Java AppEngine proporciona un conjunto de servicios escalables que pueden utilizar las aplicaciones para: Almacenar datos persistentes. En Java, el almacén de datos admite 2 interfaces Java estándar: 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 través de la URL Fectch API. Cachear información. Memcache de AppEngine proporciona un almacenamiento en caché distribuido, transitorio y rápido de los resultados de cálculos y consultas de almacén de datos. La interfaz Java implementa JCache (JSR 107). Enviar email. Da soporte de JavaMail para el envío de correos Procesar imágenes. A través de la Images Java API, permite a las aplicaciones transformar y manipular datos de imágenes en varios formatos. Gestionar usuarios. A través de la Users Java API permite utilizar Cuentas de Google para la autenticación del usuario. Lanzar tareas planificadas o en background. Mediante la TaskQueue Java API y la gestión de tareas por Cron.
  • 31. Instalación de AppEnginefor Java Descargar el fichero de: http://code.google.com/intl/es/appengine/downloads.html#Google_App_Engine_SDK_for_Java Descomprimir el fichero .zip Crear una variable de entorno APPENGINE_JAVA_SDK que apunte al directorio raíz de instalación de la SDK Incluir el directorio %APPENGINE_JAVA_SDK%inen la variable de entorno PATH
  • 32. Pasos para crear una Aplicación con Google AppEngine para Java Crear el proyecto de la aplicación Crear la clase servlet Crear el fichero de despliegue de la aplicación: web.xml Crear el archivo appengine-web.xml Ejecutar el proyecto Probar el proyecto: http://localhost:8080/<nombre-aplicación> Subir la aplicación al dominio appspot.com
  • 33. Configuración del Entorno Instalar java Descomprimir la distribución de GAE for Java a una carpeta de tu disco duro Modificar la variable de entorno APPENGINE_JAVA_SDK para que apunte a ese directorio Modificar la variable de entorno PATH para que apunte a %APPENGINE_JAVA_SDK%in Descomprimir el fichero downloadspache-ant-1.8.1-bin.zip Modificar la variable de entorno PATH para que apunte a <ANT_DIR>in cdexamplesoogleappengineavauestbook ant
  • 34. Paso 1: Creando la estructura del proyecto Dos opciones: Usar el plug-in para Eclipse: http://code.google.com/intl/es/appengine/docs/java/tools/eclipse.html Usar la plantilla de proyecto disponible en %APP_ENGINE_HOME%emosew_project_template Las aplicaciones Java de AppEngine utilizan el API Java Servlet para interactuar con el servidor web. Un servlet HTTP es una clase de aplicación que puede procesar y responder solicitudes web. Esta clase amplía 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 sourcecode... META-INF/ ...otherconfiguration... war/ ...JSPs, images, data files... WEB-INF/ ...appconfiguration... classes/ ...compiledclasses... lib/ ...JARsforlibraries...
  • 35. Paso 2: Creando la clase Servlet Crear en el directorio src/guestbook/ un fichero denominado GuestbookServlet.java con el siguiente contenido: packageguestbook;importjava.io.IOException;importjavax.servlet.http.*;publicclassGuestbookServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq, HttpServletResponseresp) throwsIOException {    resp.setContentType("text/plain");      resp.getWriter().println("Hello, world");   }}
  • 36. 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 configuración conocido como "descriptor de implementación de la aplicación web". Este archivo se denomina web.xml y se ubica en el directorio war/WEB-INF/ del directorio que contiene los ficheros de una aplicación web en Java <?xmlversion="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-appxmlns="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>
  • 37. Paso 4: Crear el fichero de configuración de aplicación GAE: appengine-web.xml AppEngine necesita un archivo de configuración adicional para poder desarrollar y ejecutar la aplicación, denominado appengine-web.xml  Se ubica en WEB-INF/ junto a web.xml. Incluye la ID registrada de la aplicación, el número de versión de la aplicación y listas de archivos que se deben tratar como archivos estáticos (por ejemplo, imágenes y CSS) y archivos de recursos (por ejemplo, JSP y otros datos de aplicación). El directorio war/WEB-INF/ incluye un archivo denominado appengine-web.xml que contiene lo siguiente: <?xmlversion="1.0" encoding="utf-8"?> <appengine-web-appxmlns="http://appengine.google.com/ns/1.0"> <application>librocitas</application> <version>1</version> </appengine-web-app>
  • 38. Paso 5: Ejecución del Proyecto El SDK de AppEngine incluye un servidor web de pruebas para depurar tu aplicación. El servidor simula los servicios y el entorno AppEngine, que incluyen restricciones en la zona de pruebas, el almacén de datos y los servicios. Con el fichero ant ejecuta: antrunserver Puedes detenerlo con Ctrl-C
  • 39. Paso 6: Subiendo la aplicación Puedes crear y administrar aplicaciones web AppEngine con la consola de administración de AppEngine a través de la siguiente URL: http://appengine.google.com/ Para crear una nueva aplicación, haz clic en el botón "CreateanApplication" (Crear aplicación) Edita el archivo appengine-web.xml y, a continuación, cambia el valor del elemento <application> para que sea la ID registrada de tu aplicación (librocitas). Ejecuta el siguiente comando en línea de comandos para subir la aplicación: $ appcfg update www Vete a: http://librocitas.appspot.com/
  • 40. El fichero de Ant Apache Ant facilita la administración de tu proyecto desde la línea 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 AppEngine, entre las que se incluyen: El inicio del servidor de desarrollo y La subida de la aplicación a AppEngine Algunos problemas con el build.xml suministrado por new-project-template Fichero adaptado en examples/guestbook/build.xml: Hay que definir variable de entorno APP_ENGINE_SDK para desligar build.xml de su localización en disco Introducir tarea para copiar jars con dependencias
  • 41. Usando el Servicio de Usuarios Google AppEngine ofrece varios servicios útiles basados en la infraestructura de Google a los que se puede acceder a través 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 aplicación con cuentas de usuarios de Google packageguestbook;importjava.io.IOException;importjavax.servlet.http.*;importcom.google.appengine.api.users.User;importcom.google.appengine.api.users.UserService;importcom.google.appengine.api.users.UserServiceFactory;publicclassGuestbookServletextendsHttpServlet {    publicvoiddoGet(HttpServletRequestreq, HttpServletResponseresp)              throwsIOException {        UserServiceuserService = UserServiceFactory.getUserService();        Useruser = userService.getCurrentUser();        if (user != null) {            resp.setContentType("text/plain");            resp.getWriter().println("Hello, " + user.getNickname());        } else {            resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));        }    }}
  • 42. Uso de un JSP Aunque podríamos generar el código HTML para la interfaz de usuario directamente a partir del código Java del servlet, no sería algo fácil de mantener, ya que el código HTML se complica Es más conveniente utilizar un sistema de plantillas, en el que la interfaz de usuario esté diseñada e implementada en archivos independientes con marcadores y lógica para insertar datos proporcionados por la aplicación. 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 código fuente Java y, a continuación, compila este código en código de bytes de Java Al subir la aplicación a AppEngine, el SDK compila todas las JSP en código de bytes y únicamente sube el código de bytes.
  • 43. 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><% UserServiceuserService = UserServiceFactory.getUserService(); Useruser = userService.getCurrentUser(); if (user != null) {%> <p>Hello, <%= user.getNickname() %>! (You can<a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">signout</a>.)</p><% } else {%> <p>Hello!<a href="<%= userService.createLoginURL(request.getRequestURI()) %>">Sign in</a>toincludeyournamewithgreetingsyou post.</p><% }%> </body>
  • 44. Formulario Libro Invitados La aplicación 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 código 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>
  • 45. El Servlet que Procesa una Nueva Entrada en Libro packageguestbook; importjava.io.IOException; importjava.util.logging.Logger; importjavax.servlet.http.*; importcom.google.appengine.api.users.User; importcom.google.appengine.api.users.UserService; importcom.google.appengine.api.users.UserServiceFactory; publicclassSignGuestbookServletextendsHttpServlet { privatestatic final Logger log = Logger.getLogger(SignGuestbookServlet.class.getName()); publicvoiddoPost(HttpServletRequestreq, HttpServletResponseresp) throwsIOException{ UserServiceuserService = UserServiceFactory.getUserService(); Useruser = userService.getCurrentUser(); Stringcontent = req.getParameter("content"); if (content == null) { content = "(No greeting)"; } if (user != null) { log.info("Greetingpostedbyuser " + user.getNickname() + ": " + content); } else { log.info("Greetingpostedanonymously: " + content); } resp.sendRedirect("guestbook.jsp"); } }
  • 46. Logeo de Información con AppEngine El nuevo servlet utiliza la clase java.util.logging.Logger para escribir mensajes en el registro. Puedes controlar el comportamiento de esta clase a través de un archivo logging.properties y de un conjunto de propiedades del sistema en el archivo appengine-web.xml de la aplicación. Copia el archivo de ejemplo del SDK appengine-java-sdk/config/user/logging.properties en el directorio war/WEB-INF/ de la aplicación  Para modificar el nivel de registro de todas las clases del paquete guestbook, edita el archivo logging.properties y añade una entrada para guestbook.level, como se muestra a continuación: .level = WARNING guestbook.level = INFO A continuación edita el archivo war/WEB-INF/appengine-web.xml de la aplicación como se indica: <appengine-web-appxmlns="http://appengine.google.com/ns/1.0"> ... <system-properties> <propertyname="java.util.logging.config.file" value="WEB-INF/logging.properties"/> </system-properties> </appengine-web-app> Los ficheros de logeo se descargan con la consola de administración o la aplicación appcfg de AppEngine: https://appengine.google.com/logs
  • 47. Uso del Almacen de Datos JDO La infraestructura de AppEngine se encarga de todas las tareas de distribución, replicación y balanceo de carga de los datos de un API sencilla, además de ofrecer un potente motor de consulta y transacciones. Ofrece dos API: un API estándar y otra de nivel inferior. AppEnginefor Java permite el uso de dos estándares de API diferentes para el almacén de datos: Objetos de datos Java (JDO) y API de persistencia Java (JPA). Estas interfaces las proporciona DataNucleus Access Platform, una implementación de software libre de varios estándares de persistencia Java, con un adaptador para Google DataStore Utilizaremos la interfaz JDO para la recuperación y la publicación de los mensajes de los usuarios en el almacén de datos de AppEngine. Access Platformnecesita un archivo de configuración que le indique que debe utilizar el almacén de datos de AppEngine como servidor para la implementación de JDO: META-INF/jdoconfig.xml Documentación detallada de JDO puede encontrarse en: http://code.google.com/appengine/docs/java/datastore/
  • 48. Funcionamiento de JDO Al crear clases JDO, debes utilizar anotaciones Java para describir cómo se deben guardar las instancias en el almacén de datos y cómo se deben volver a crear al recuperarlas de dicho almacén. Access Platform conecta las clases de datos a la implementación mediante un paso de procesamiento posterior a la compilación, que DataNucleus denomina "mejora" de las clases. JDO permite almacenar objetos Java (a veces denominados "objetos Java antiguos y simples" o POJO) en cualquier almacén de datos con un adaptador compatible con JDO, como DataNucleus Access Platform El complemento Access Platform para el almacén de datos de AppEngine permite almacenar instancias de clases definidas en el almacén de datos de AppEngine Ejemplo: la clase Greeting representará mensajes individuales publicados en el libro de invitados de nuestra aplicación
  • 49. La Clase de Persistencia Greeting packageguestbook; importjava.util.Date; importjavax.jdo.annotations.IdGeneratorStrategy; importjavax.jdo.annotations.IdentityType; importjavax.jdo.annotations.PersistenceCapable; importjavax.jdo.annotations.Persistent; importjavax.jdo.annotations.PrimaryKey; importcom.google.appengine.api.users.User; @PersistenceCapable(identityType = IdentityType.APPLICATION) publicclassGreeting { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Long id; @Persistent privateUserauthor; @Persistent privateStringcontent; @Persistent private Date date; publicGreeting(Userauthor, Stringcontent, Date date) { this.author = author; this.content = content; this.date = date; } ... }
  • 50. La Clase de Persistencia Greeting Esta sencilla clase define tres propiedades para un saludo: author, content y date Estos tres campos privados presentan la anotación @Persistent, que indica a DataNucleus que debe almacenarlos como propiedades de objetos en el almacén de datos de AppEngine. La clase también define un campo llamado id, una clave Long que presenta dos anotaciones: @Persistent y @PrimaryKey. El almacén de datos de AppEngine tiene una noción de las claves de entidades y puede representar las claves de varias formas en un objeto. Más información sobre cómo definir modelos de datos puede encontrarse en: http://code.google.com/intl/es/appengine/docs/java/datastore/dataclasses.html
  • 51. Serializando datos con JDO Cada solicitud que utiliza el almacén de datos crea una nueva instancia de la clase PersistenceManager que se obtiene a través de PersistenceManagerFactory Una instancia de PersistenceManagerFactory tarda algún tiempo en inicializarse Afortunadamente, sólo se necesita una instancia para cada aplicación Creamos la clase singletonPMF para resolverlo: packageguestbook; importjavax.jdo.JDOHelper; importjavax.jdo.PersistenceManagerFactory; public final class PMF { privatestatic final PersistenceManagerFactorypmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional"); private PMF() {} publicstaticPersistenceManagerFactoryget() { returnpmfInstance; } } Para usarlo creamos una nueva instancia de Greeting mediante la ejecución del constructor. Para guardar la instancia en el almacén de datos, crea una clase PersistenceManager a través de PMF.get() e invocamos sobre él makePersistent()
  • 52. Serializando datos con JDO Dentro del fichero SignGuestBookServlet introduciríamos los siguientes cambios para serializar los saludos en AppEngineDataStore, a través de JDO: Stringcontent = req.getParameter("content"); Date date = new Date(); Greetinggreeting = new Greeting(user, content, date); PersistenceManager pm = PMF.get().getPersistenceManager(); try { pm.makePersistent(greeting); } finally { pm.close(); }
  • 53. Consultando datos con JDO El estándar 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>Theguestbook has no messages.</p> <% } else { for (Greeting g : greetings) { if (g.getAuthor() == null) { %> <p>Ananonymouspersonwrote:</p> <% } else { %> <p><b><%= g.getAuthor().getNickname() %></b> wrote:</p> <% } %> <blockquote><%= g.getContent() %></blockquote> <% } } pm.close(); %>
  • 54. Usando Ficheros Estáticos Hay muchos casos en los que querrás mostrar los archivos estáticos directamente en el navegador web: imágenes, vídeos Para una mayor eficiencia, AppEngine muestra los archivos estáticos desde servidores independientes en lugar de los que ejecutan servlets. AppEngine considera todos los archivos del directorio WAR como archivos estáticos, salvo JSP y los archivos de WEB-INF/ Cualquier solicitud de una URL cuya ruta coincida con un archivo estático lo muestra Puedes configurar los archivos que quieres que AppEngine considere como archivos estáticos a través del archivo appengine-web.xml La siguiente página da más información 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; } Añadir a guestbook.jsp lo siguiente: <head> <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> </head>
  • 55. Creando de Objetos y Claves Para almacenar un objeto de datos sencillo en el almacén de datos, ejecuta el método makePersistent() del PersistenceManager y transfiérelo 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 más sencillas están basadas en los tipos Long o String, pero también se pueden crear con la clase Key. importcom.google.appengine.api.datastore.Key; importcom.google.appengine.api.datastore.KeyFactory; // ... Key k = KeyFactory.createKey(Employee.class.getSimpleName(), "Alfred.Smith@example.com"); Para recuperar un elemento por clave podemos usar lo siguiente, se puede pasar como segundo argumento una clave, un entero o un string: Employee e = pm.getObjectById(Employee.class, "Alfred.Smith@example.com");
  • 56. Actualización y Borrado de Objetos El siguiente código muestra cómo actualizar un objeto persistente: publicvoidupdateEmployeeTitle(Useruser, StringnewTitle) { 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 cómo borrar un objeto: pm.deletePersistent(e);
  • 57. Realizando Consultas con JDO JDOQL es similar a SQL, aunque es más adecuado para bases de datos relacionadas con objetos, como, por ejemplo, el almacén de datos de AppEngine. Dos usos diferentes: Puedes especificar parte o la totalidad de la consulta mediante métodos de ejecución en el objeto de consulta importjava.util.List; importjavax.jdo.Query; // ... Queryquery = pm.newQuery(Employee.class); query.setFilter("lastName == lastNameParam"); query.setOrdering("hireDatedesc"); query.declareParameters("StringlastNameParam"); try { List<Employee> results = (List<Employee>) query.execute("Smith"); if (results.iterator().hasNext()) { for (Employee e : results) { // ... } } else { // ... no results ... } } finally { query.closeAll(); }
  • 58. Realizando Consultas con JDO Puedes especificar una consulta completa en una cadena mediante la sintaxis de cadena JDOQL: Queryquery = pm.newQuery("selectfromEmployee " +    "wherelastName == lastNameParam " +    "orderbyhireDatedesc " +    "parametersStringlastNameParam"); List<Employee> results = (List<Employee>) query.execute("Smith"); Otro modo: Queryquery = pm.newQuery(Employee.class,    "lastName == lastNameParamorderbyhireDatedesc"); query.declareParameters("StringlastNameParam"); List<Employee> results = (List<Employee>) query.execute("Smith"); Query query = pm.newQuery(Employee.class,    "lastName == 'Smith' order by hireDatedesc");
  • 59. Filtros y Restricciones en Consultas JDO sobre AppEngine Algunos ejemplos de filtros son: query.setFilter("lastName == 'Smith' && hireDate > hireDateMinimum"); query.declareParameters("Date hireDateMinimum"); Queryquery = pm.newQuery(Employee.class,    "(lastName == 'Smith' || lastName == 'Jones')" +    " && firstName == 'Harold'"); ATENCIÓN: 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 sólo están permitidos en una propiedad
  • 60. Ejemplo Objeto Serializable La siguiente clase define un objeto que puede serializarse en JDO: importjava.io.Serializable; publicclassDownloadableFileimplementsSerializable{ private byte[] content; privateStringfilename; privateStringmimeType; // ... accessors ... } La siguiente clase define cómo usarlo: importjavax.jdo.annotations.Persistent; importDownloadableFile; // ... @Persistent(serialized = "true"); privateDownloadableFilefile;
  • 61. Ejemplo Relación 1 a 1 entre Entidades importcom.google.appengine.api.datastore.Key; // ... imports ... @PersistenceCapable publicclassContactInfo { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent privateStringstreetAddress; @Persistent privateStringcity; @Persistent privateStringstateOrProvince; @Persistent privateStringzipCode; // ... accessors ... } importContactInfo; // ... imports ... @PersistenceCapable publicclassEmployee { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent privateContactInfomyContactInfo; // ... accessors ... }
  • 62. Relaciones Uno a Varios Ejemplo de relación bidireccional uno a varios: // Employee.java importjava.util.List; // ... @Persistent private List<ContactInfo> contactInfoSets; // ContactInfo.java importEmployee; // ... @Persistent privateEmployeeemployee;
  • 63. Relaciones Varios a Varios Ejemplo de relación varios a varios, sólo se puede hacer guardando colecciones de claves en ambas relaciones implicadas: //Person.java importjava.util.Set; importcom.google.appengine.api.datastore.Key; // ... @Persistent private Set<Key> favoriteFoods; //Food.java importjava.util.Set; importcom.google.appengine.api.datastore.Key; // ... @Persistent private Set<Key> foodFans; // Album.java // ... publicvoidaddFavoriteFood(Foodfood) { favoriteFoods.add(food.getKey()); food.getFoodFans().add(getKey()); } publicvoidremoveFavoriteFood(Foodfood) { favoriteFoods.remove(food.getKey()); food.getFoodFans().remove(getKey()); }
  • 64. Características Avanzadas de Google AppEngine Planificación 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 Envío de mensajes instantáneos con XMPP e email http://code.google.com/appengine/docs/java/xmpp/overview.html Colas de tareas – permite ejecutar asíncronamente tareas http://code.google.com/appengine/docs/java/taskqueue/overview.html
  • 65. Planificación de Tareas con Cron El servicio AppEngine Cron Service permite planificar tareas que se ejecutan en un momento o periodos determinados. Los trabajos cron (cron jobs) son ejecutados por AppEngine Cron Service Algunos ejemplos de uso serían: Envío de email con informe diario Actualización de tu caché de datos cada 10 minutos Documentación en: http://code.google.com/appengine/docs/java/config/cron.html Formato de las planificaciones: ("every"|ordinal) (days) ["of" (monthspec)] (time)
  • 66. Planificación de Tareas con Cron El fichero WEB-INFron.xmlcontrolacronparatuaplicación: <?xmlversion="1.0" encoding="UTF-8"?> <cronentries> <cron> <url>/recache</url>  <description>Repopulatethe cache every 2 minutes</description>  <schedule>every 2 minutes</schedule></cron><cron> <url>/weeklyreport</url>  <description>Mail out a weeklyreport</description>  <schedule>everymonday 08:30</schedule>  <timezone>America/New_York</timezone></cron> </cronentries>
  • 67. 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 AppEngine incluye un servicio de memoria caché El API Java de Memcache implementa la interfaz JCache (javax.cache), un estándar 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 cuándo los valores vencen en la memoria caché Inspeccionar el contenido de la memoria caché y obtener estadísticas sobre ella Utilizar "funciones de escucha" para añadir un comportamiento personalizado al establecer y borrar valores.
  • 68. Pasos para Hacer uso de Memcache Obtención y configuración de una instancia de Cache, para ello hay que configurar los parámetros del método createCache importjavax.cache.Cache; importjavax.cache.CacheException; importjavax.cache.CacheFactory; // ... Cache cache; try { Mapprops = new Map; props.put(GCacheFactory.EXPIRATION_DELTA, 3600); props.put(MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT, true); CacheFactorycacheFactory = CacheManager.getInstance().getCacheFactory(); // cache = cacheFactory.createCache(Collections.emptyMap()); cache = cacheFactory.createCache(props); } catch (CacheException e) { // ... } Establecimiento y obtención de valores. Se comporta como un mapa Puedes almacenar claves y valores a través del método put() y recuperar valores con el método get() Otros métodos de interés son: remove(), clear(), containsKey(), isEmpty() y size() Más documentación en: http://code.google.com/intl/es/appengine/docs/java/memcache/usingjcache.html
  • 69. URL Fetch Java API GAE permite realizar conexiones HTTP y HTTPS a través 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 página mediante java.net.URL y el método openStream() El método 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 conexión como: Añadir cabeceras: connection.setRequestProperty("X-MyApp-Version", "2.7.3"); Modificar el hecho de que las peticiones se redirijan directamente: connection.setRequestProperty("X-MyApp-Version", "2.7.3"); Más detalles en: http://code.google.com/intl/en/appengine/docs/java/urlfetch/usingjavanet.html
  • 70. Mail Java API Una aplicación en AppEngine puede enviar mensajes en representación del administrador de la página o de usuarios autorizados con cuentas Google La Mail Service Java API hace uso de javax.mail Se puede configurar tu aplicación para recibir mensajes en una dirección con el formato string@appid.appspotmail.com Cuando una aplicación se ejecuta en el servidor de desarrollo, el mensaje enviado se imprime en el log, no se envía
  • 71. Enviando un Mensaje ... importjava.util.Properties; importjavax.mail.Message; importjavax.mail.MessagingException; importjavax.mail.Session; importjavax.mail.Transport; importjavax.mail.internet.AddressException; importjavax.mail.internet.InternetAddress; importjavax.mail.internet.MimeMessage; // ... Propertiesprops = new Properties(); Sessionsession = Session.getDefaultInstance(props, null); StringmsgBody = "...“; try { Messagemsg = 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 beenactivated"); msg.setText(msgBody); Transport.send(msg); } catch (AddressException e) { // ... } catch (MessagingException e) { // ... }
  • 72. Recibiendo un Mensaje Los pasos a seguir son: Configurar tu aplicación para ser receptora de email en la dirección: string@appid.appspotmail.com Modificando el fichero appengine-web.xml: <inbound-services> <service>mail</service> </inbound-services> Modificando el fichero web.xml, que recibirá mensajes en la siguiente dirección: /_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>
  • 73. Recibiendo un Mensaje Los pasos a seguir son: Crear un servlet que reciba los mensajes importjava.io.IOException; importjava.util.Properties; importjavax.mail.Session; importjavax.mail.internet.MimeMessage; importjavax.servlet.http.*; publicclassMailHandlerServletextendsHttpServlet{ publicvoiddoPost(HttpServletRequestreq, HttpServletResponseresp) throwsIOException { Propertiesprops = new Properties(); Sessionsession = Session.getDefaultInstance(props, null); MimeMessagemessage = new MimeMessage(session, req.getInputStream()); … }
  • 74. TaskQueue API Una aplicación Java puede crear una cola configurada en el fichero de configuración WEB-INF/queue.xml  Para encolar una tarea, hay que obtener una instancia de Queue usando una QueueFactory y luego invocar el método add() Puedes obtener una cola por nombre declarada en el fichero queue.xml o la cola por defecto con el método getDefaultQueue() Se puede añadir una tarea a la cola pasando una instancia de TaskOptions al método add() Se invocará un servlet que será quien ejecute la tarea encolada (ver ejemplo siguiente trasparencia) Espacio de nombres en versión beta: com.google.appengine.api.labs.taskqueue
  • 75. Ejemplo de TaskQueue API El siguiente ejemplo muestra cómo añadir una tarea a una cola: importcom.google.appengine.api.labs.taskqueue.Queue; importcom.google.appengine.api.labs.taskqueue.QueueFactory; importstaticcom.google.appengine.api.labs.taskqueue.TaskOptions.Builder.*; // ... Queuequeue = QueueFactory.getDefaultQueue(); queue.add(url("/worker").param("key", key));
  • 76. Ejemplo de TaskQueue API Ejemplo de queue.xml, donde s indica segundos, m minutos, h horas y d días, es decir, la frecuencia con la que las tareas encoladas serían procesadas: <queue-entries>  <queue>    <name>default</name>    <rate>1/s</rate>  </queue>  <queue>    <name>mail-queue</name>    <rate>2000/d</rate>    <bucket-size>10</bucket-size>  </queue>  <queue>    <name>background-processing</name>    <rate>5/s</rate>  </queue></queue-entries>
  • 77. Combinando Struts2 y GAE Revisar ejemplo: struts2tutorial Modificaciones a realizar en la distribución de struts2tutorial: Reimplementar la clase freemarker.core.TextBlock Inicializar a null el SecurityManager de OgnlRuntime Explicación de cómo hacerlo en: http://whyjava.wordpress.com/2009/08/30/creating-struts2-application-on-google-app-engine-gae/
  • 78. Pluginfor 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/
  • 79. Importación y Exportación de Datos Se pueden acceder a datos detrás de tu Intranet desde una aplicación de Google AppEngine, 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/uploadingdata.html
  • 80. Google AppEnginefor Business Las aplicaciones generadas con AppEnginefor Business usan las APIs de Java y Python, pero permiten acceder al desarrollador a capacidades especiales (premium): Acceso a SSL y SQL Tendrán un coste adicional Mas información en: http://code.google.com/appengine/business/
  • 81. Limitaciones Google AppEngine El servicio tiene varias limitaciones: Solo hasta recientemente no todo el mundo podía acceder a él Es gratis durante el periodo de pruebas, pero con límites de uso: 500 MB de almacenamiento, 200 millones de megaciclos/día 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 técnicas originales parcialmente resueltas: Los desarrolladores solamente tienen acceso de lectura al sistema de ficheros de AppEngine Solamente se puede ejecutar código a partir de una petición HTTP Solamente se puede subir código 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á detrás de Google AppEngine
  • 82. Google App Engine vs. Amazon Web Services A primera vista Google AppEngine es un competidor a la suite de servicios web ofrecida por Amazon: S3 para almacenamiento EC2 para la creación de servidores virtuales SimpleDB como base de datos Pero … Google AppEngine es una plataforma mucho más 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)
  • 83. Google App Engine vs. Amazon Web Services
  • 84. Referencias Google AppEngine http://code.google.com/appengine/
  • 85. Cloud Computing: Google App Engine31 de Mayo de 2011, 18:00-21:00 Dr. Diego Lz. de Ipiña Glz. de Artazadipina@deusto.eshttp://paginaspersonales.deusto.es/dipinahttp://www.slideshare.net/dipinahttp://www.morelab.deusto.es