Ofrece una plataforma completa para el alojamiento y escalado automtico de aplicaciones, consistiendo en: Servidores de aplicaciones Python y Java La base de datos BigTable El sistema de ficheros GFS Como desarrollador simplemente tienes que subir tu cdigo Python o Java compilado a Google, lanzar la aplicacin y monitorizar el uso y otras mtricas Google AppEngine incluye la librera estndar de Python 2.5 y soporta Java 1.6 No todas las acciones se permiten (acceso a ficheros, llamadas al SO, algunas llamadas de red) Se ejecuta en un entorno restringido para permitir que las aplicaciones escalen Ejemplo: https://appengine.google.com http://enpresadigitala.appspot.com/encuestas http://code.google.com/intl/en/appengine/docs/ 9. Google AppEngine: Python y Java Vamos a revisar primero (brevemente) cmo realizar aplicaciones con Python Luego nos centraremos en cmo hacerlo desde Java en mayor grado de detalle
11. Principios Una aplicacin de AppEngine se comunica con el servidor que la aloja a travs de CGI Cuando recibe una peticin el servidor lee de la entrada estndar y de las variables de entorno Cuando genera una respuesta escribe a la salida estndar
12. Mi primera aplicacin Crear el directorio helloworld Crea el fichero helloworld.py dentro de l con el siguiente contenido, que corresponde a una respuesta HTTP: print 'Content-Type: text/plain' print '' print 'Hello, world! Crea el fichero de configuracin requerido por toda aplicacin 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/
El switch--help da ms indicaciones sobre las opciones aceptadas por el servidor Vete a la siguiente URL para probarlo: http://localhost:8080/
13. Ejecutando Hola Mundo en Google App Engine
14. Opciones Avanzadas para GAE forPython Framework webapp que soporta el estndar WSGI Acceso a datos de usuarios mediante la Users API DataStore API Plantillas en Google AppEngine
15. Usando el Almacn de Datos de Google AppEngine Guardar datos en una aplicacin web escalable puede ser difcil La infraestructura de AppEngine se encarga de la distribucin, replicacin y balanceo de carga de los datos detrs de una API sencilla que tambin ofrece un motor de consultas y transacciones App Engine incluye una API de modelado de datos para Python Se asemeja a la API de Django pero utiliza el servidor de datos escalable BigTable por detrs. No 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 ms 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)
24. Subiendo la aplicacin Es necesario realizar los siguientes pasos: Editar el fichero app.yaml file y cambiar el valor de la aplicacin: de helloworld al nombre de id de aplicacin (enpresadigitala) Ejecutar el siguiente comando: appcfg.py updatehelloworld/ Acceder a la aplicacin en http://application-id.appspot.com, por ejemplo en http://enpresadigitala.appspot.com/
App Engine para Java Crea aplicaciones web a travs de tecnologas estndar de Java y las ejecuta en la infraestructura escalable Google Usa JVM Java 6, interfaz de servlets Java y la compatibilidad de interfaces estndar como JDO, JPA, JavaMail y JCache AppEngine utiliza el estndar Java Servlet para aplicaciones web JVM se ejecuta en un entorno seguro de la "zona de pruebas" para aislar tu aplicacin por servicio y seguridad. Una aplicacin en GAE slo pueda realizar acciones que no interfieran con el rendimiento ni con la escalabilidad de otras aplicaciones.
30. Funcionalidad de AppEnginefor Java AppEngine proporciona un conjunto de servicios escalables que pueden utilizar las aplicaciones para: Almacenar datos persistentes. En Java, el almacn de datos admite 2 interfaces Java estndar: los objetos de datos Java (JDO) 2.3 y el API de persistencia de Java (JPA) 1.0. Acceder a recursos en la red. A travs de la URL Fectch API. Cachear informacin. Memcache de AppEngine proporciona un almacenamiento en cach distribuido, transitorio y rpido de los resultados de clculos y consultas de almacn de datos. La interfaz Java implementa JCache (JSR 107). Enviar email. Da soporte de JavaMail para el envo de correos Procesar imgenes. A travs de la Images Java API, permite a las aplicaciones transformar y manipular datos de imgenes en varios formatos. Gestionar usuarios. A travs de la Users Java API permite utilizar Cuentas de Google para la autenticacin del usuario. Lanzar tareas planificadas o en background. Mediante la TaskQueue Java API y la gestin de tareas por Cron.
31. Instalacin 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 raz de instalacin de la SDK Incluir el directorio %APPENGINE_JAVA_SDK%binen la variable de entorno PATH
32. Pasos para crear una Aplicacin con Google AppEngine para Java Crear el proyecto de la aplicacin Crear la clase servlet Crear el fichero de despliegue de la aplicacin: web.xml Crear el archivo appengine-web.xml Ejecutar el proyecto Probar el proyecto: http://localhost:8080/<nombre-aplicacin> Subir la aplicacin al dominio appspot.com
33. Configuracin del Entorno Instalar java Descomprimir la distribucin 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%bin Descomprimir el fichero downloadsapache-ant-1.8.1-bin.zip Modificar la variable de entorno PATH para que apunte a <ANT_DIR>bin cdexamplesgoogleappenginejavaguestbook 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%demosnew_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 aplicacin que puede procesar y responder solicitudes web. Esta clase ampla la clase javax.servlet.GenericServlet o a la clase javax.servlet.http.HttpServlet. La estructura del directorio de trabajo ser la siguiente: Guestbook/ src/ ...Java 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.*;publicclassGu estbookServletextendsHttpServlet{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 configuracin conocido como "descriptor de implementacin de la aplicacin web". Este archivo se denomina web.xml y se ubica en el directorio war/WEB-INF/ del directorio que contiene los ficheros de una aplicacin web en Java <?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 configuracin de aplicacin GAE: appengine-web.xml AppEngine necesita un archivo de configuracin adicional para poder desarrollar y ejecutar la aplicacin, denominado appengine-web.xml Se ubica en WEB-INF/ junto a web.xml. Incluye la ID registrada de la aplicacin, el nmero de versin de la aplicacin y listas de archivos que se deben tratar como archivos estticos (por ejemplo, imgenes y CSS) y archivos de recursos (por ejemplo, JSP y otros datos de aplicacin). El directorio war/WEB-INF/ incluye un archivo denominado 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: Ejecucin del Proyecto El SDK de AppEngine incluye un servidor web de pruebas para depurar tu aplicacin. El servidor simula los servicios y el entorno AppEngine, que incluyen restricciones en la zona de pruebas, el almacn de datos y los servicios. Con el fichero ant ejecuta: antrunserver Puedes detenerlo con Ctrl-C
39. Paso 6: Subiendo la aplicacin Puedes crear y administrar aplicaciones web AppEngine con la consola de administracin de AppEngine a travs de la siguiente URL: http://appengine.google.com/ Para crear una nueva aplicacin, haz clic en el botn "CreateanApplication" (Crear aplicacin) Edita el archivo appengine-web.xml y, a continuacin, cambia el valor del elemento <application> para que sea la ID registrada de tu aplicacin (librocitas). Ejecuta el siguiente comando en lnea de comandos para subir la aplicacin: $ appcfg update www Vete a: http://librocitas.appspot.com/
40. El fichero de Ant Apache Ant facilita la administracin de tu proyecto desde la lnea de comandos o desde otros entornos de desarrollo integrados (IDE) compatibles con Ant. El SDK de Java incluye un conjunto de macros de Ant para realizar tareas de desarrollo de AppEngine, entre las que se incluyen: El inicio del servidor de desarrollo y La subida de la aplicacin 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 localizacin 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 travs de aplicaciones utilizando una serie de bibliotecas incluidas en el kit de desarrollo de software (SDK) Por ejemplo, el servicio de usuarios te permite integrar tu aplicacin con cuentas de usuarios de Google packageguestbook;importjava.io.IOException;importjavax.servlet.http.*;importcom.go ogle.appengine.api.users.User;importcom.google.appengine.api.users.UserService;imp ortcom.google.appengine.api.users.UserServiceFactory;publicclassGuestbookServletex tendsHttpServlet { 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 podramos generar el cdigo HTML para la interfaz de usuario directamente a partir del cdigo Java del servlet, no sera algo fcil de mantener, ya que el cdigo HTML se complica Es ms conveniente utilizar un sistema de plantillas, en el que la interfaz de usuario est diseada e implementada en archivos independientes con marcadores y lgica para insertar datos proporcionados por la aplicacin. Pasos: En el directorio war/, crea un archivo llamado guestbook.jsp con el contenido de la siguiente transparencia Modificar el fichero web.xml para que el welcome-file apunte a guestbook.jsp Acceder a la ruta: http://localhost:8080/guestbook.jsp o http://localhost:8080/ Al cargar una JSP por primera vez, el servidor de desarrollo lo convierte en cdigo fuente Java y, a continuacin, compila este cdigo en cdigo de bytes de Java Al subir la aplicacin a AppEngine, el SDK compila todas las JSP en cdigo de bytes y nicamente sube el cdigo de bytes.
44. Formulario Libro Invitados La aplicacin de libro de invitados necesita un formulario web para que el usuario publique un nuevo saludo, as como una forma de procesar ese formulario El cdigo HTML del formulario se inserta en la JSP guestbook.jsp: <form action="/sign" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Post Greeting" /></div> </form> El destino del formulario es una nueva URL, /sign, controlada por una nueva clase de servlet,SignGuestbookServlet que procesa el formulario y redirige a: /guestbook.jsp Es necesario modificar web.xml para crear una nueva entrada para este servlet, con los siguientes datos: <servlet> <servlet-name>sign</servlet-name> <servlet-class>guestbook.SignGuestbookServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sign</servlet-name> <url-pattern>/sign</url-pattern> </servlet-mapping>
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 Informacin 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 travs de un archivo logging.properties y de un conjunto de propiedades del sistema en el archivo appengine-web.xml de la aplicacin. Copia el archivo de ejemplo del SDK appengine-java- sdk/config/user/logging.properties en el directorio war/WEB-INF/ de la aplicacin Para modificar el nivel de registro de todas las clases del paquete guestbook, edita el archivo logging.properties y aade una entrada para guestbook.level, como se muestra a continuacin: .level = WARNING guestbook.level = INFO A continuacin edita el archivo war/WEB-INF/appengine-web.xml de la aplicacin como se indica: <appengine-web-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 administracin o la aplicacin 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 distribucin, replicacin y balanceo de carga de los datos de un API sencilla, adems de ofrecer un potente motor de consulta y transacciones. Ofrece dos API: un API estndar y otra de nivel inferior. AppEnginefor Java permite el uso de dos estndares de API diferentes para el almacn de datos: Objetos de datos Java (JDO) y API de persistencia Java (JPA). Estas interfaces las proporciona DataNucleus Access Platform, una implementacin de software libre de varios estndares de persistencia Java, con un adaptador para Google DataStore Utilizaremos la interfaz JDO para la recuperacin y la publicacin de los mensajes de los usuarios en el almacn de datos de AppEngine. Access Platformnecesita un archivo de configuracin que le indique que debe utilizar el almacn de datos de AppEngine como servidor para la implementacin de JDO: META- INF/jdoconfig.xml Documentacin detallada de JDO puede encontrarse en: http://code.google.com/appengine/docs/java/datastore/
48. Funcionamiento de JDO Al crear clases JDO, debes utilizar anotaciones Java para describir cmo se deben guardar las instancias en el almacn de datos y cmo se deben volver a crear al recuperarlas de dicho almacn. Access Platform conecta las clases de datos a la implementacin mediante un paso de procesamiento posterior a la compilacin, que DataNucleus denomina "mejora" de las clases. JDO permite almacenar objetos Java (a veces denominados "objetos Java antiguos y simples" o POJO) en cualquier almacn de datos con un adaptador compatible con JDO, como DataNucleus Access Platform El complemento Access Platform para el almacn de datos de AppEngine permite almacenar instancias de clases definidas en el almacn de datos de AppEngine Ejemplo: la clase Greeting representar mensajes individuales publicados en el libro de invitados de nuestra aplicacin
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 anotacin @Persistent, que indica a DataNucleus que debe almacenarlos como propiedades de objetos en el almacn de datos de AppEngine. La clase tambin define un campo llamado id, una clave Long que presenta dos anotaciones: @Persistent y @PrimaryKey. El almacn de datos de AppEngine tiene una nocin de las claves de entidades y puede representar las claves de varias formas en un objeto. Ms informacin sobre cmo definir modelos de datos puede encontrarse en: http://code.google.com/intl/es/appengine/docs/java/datastore/dataclasses.html
51. Serializando datos con JDO Cada solicitud que utiliza el almacn de datos crea una nueva instancia de la clase PersistenceManager que se obtiene a travs de PersistenceManagerFactory Una instancia de PersistenceManagerFactory tarda algn tiempo en inicializarse Afortunadamente, slo se necesita una instancia para cada aplicacin Creamos la clase 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 ejecucin del constructor. Para guardar la instancia en el almacn de datos, crea una clase PersistenceManager a travs de PMF.get() e invocamos sobre l makePersistent()
52. Serializando datos con JDO Dentro del fichero SignGuestBookServlet introduciramos los siguientes cambios para serializar los saludos en AppEngineDataStore, a travs 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 estndar JDO define un mecanismo para consultas de objetos persistentes denominado JDOQL. Modificaremos guestbook.jsp para realizar la consulta introduciendo los siguientes cambios: <%@ page import="java.util.List" %><%@ page import="javax.jdo.PersistenceManager" %><%@ page import="guestbook.Greeting" %><%@ page import="guestbook.PMF" %>
<% PersistenceManager pm = PMF.get().getPersistenceManager(); String query = "select from " + Greeting.class.getName() + " order by date desc range 0,5"; List<Greeting> greetings = (List<Greeting>) pm.newQuery(query).execute(); if (greetings.isEmpty()) { %> <p>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 Estticos Hay muchos casos en los que querrs mostrar los archivos estticos directamente en el navegador web: imgenes, vdeos Para una mayor eficiencia, AppEngine muestra los archivos estticos desde servidores independientes en lugar de los que ejecutan servlets. AppEngine considera todos los archivos del directorio WAR como archivos estticos, salvo JSP y los archivos de WEB-INF/ Cualquier solicitud de una URL cuya ruta coincida con un archivo esttico lo muestra Puedes configurar los archivos que quieres que AppEngine considere como archivos estticos a travs del archivo appengine-web.xml La siguiente pgina da ms informacin al respecto: http://code.google.com/intl/es/appengine/docs/java/config/appconfig.html Para este ejemplo: Crear main.css con el siguiente contenido: body { font-family: Verdana, Helvetica, sans-serif; background-color: #FFFFCC; } Aadir a guestbook.jsp lo siguiente: <head> <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> </head>
55. Creando de Objetos y Claves Para almacenar un objeto de datos sencillo en el almacn de datos, ejecuta el mtodo makePersistent() del PersistenceManager y transfirelo a la instancia. PersistenceManager pm = PMF.get().getPersistenceManager(); Employee e = new Employee("Alfred", "Smith", new Date()); try { pm.makePersistent(e); } finally { pm.close(); } Las claves ms sencillas estn basadas en los tipos Long o String, pero tambin se pueden crear con la clase Key. 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. Actualizacin y Borrado de Objetos El siguiente cdigo muestra cmo 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 cmo borrar un objeto: pm.deletePersistent(e);
57. Realizando Consultas con JDO JDOQL es similar a SQL, aunque es ms adecuado para bases de datos relacionadas con objetos, como, por ejemplo, el almacn de datos de AppEngine. Dos usos diferentes: Puedes especificar parte o la totalidad de la consulta mediante mtodos de ejecucin 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'"); ATENCIN: importantes restricciones en las consultas, revisar: http://code.google.com/intl/es/appengine/docs/java/datastore/queriesandindexes.ht ml#Restrictions_on_Queries Ejemplo: Los filtros de desigualdad slo estn 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 cmo usarlo: importjavax.jdo.annotations.Persistent; importDownloadableFile; // ... @Persistent(serialized = "true"); privateDownloadableFilefile;
62. Relaciones Uno a Varios Ejemplo de relacin 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 relacin varios a varios, slo 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. Caractersticas Avanzadas de Google AppEngine Planificacin de tareas con Cron for Java http://code.google.com/appengine/docs/java/config/cron.html Memcache Java API http://code.google.com/appengine/docs/java/memcache/overview.html URL Fech Java API http://code.google.com/appengine/docs/java/urlfetch/overview.html Envo de mensajes instantneos con XMPP e email http://code.google.com/appengine/docs/java/xmpp/overview.html Colas de tareas permite ejecutar asncronamente tareas http://code.google.com/appengine/docs/java/taskqueue/overview.html
65. Planificacin 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 seran: Envo de email con informe diario Actualizacin de tu cach de datos cada 10 minutos Documentacin en: http://code.google.com/appengine/docs/java/config/cron.html Formato de las planificaciones: ("every"|ordinal) (days) ["of" (monthspec)] (time)
66. Planificacin de Tareas con Cron El fichero WEB-INFcron.xmlcontrolacronparatuaplicacin: <?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 estndar en formato borrador descrito en JSR 107 JCache proporciona una interfaz en forma de mapa para recopilar datos Puedes almacenar y recuperar valores de la memoria cach mediante las claves Controlar cundo los valores vencen en la memoria cach Inspeccionar el contenido de la memoria cach y obtener estadsticas sobre ella Utilizar "funciones de escucha" para aadir un comportamiento personalizado al establecer y borrar valores.
Pasos para Hacer uso de Memcache Obtencin y configuracin de una instancia de Cache, para ello hay que configurar los parmetros del mtodo 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 obtencin de valores. Se comporta como un mapa Puedes almacenar claves y valores a travs del mtodo put() y recuperar valores con el mtodo get() Otros mtodos de inters son: remove(), clear(), containsKey(), isEmpty() y size() Ms documentacin en: http://code.google.com/intl/es/appengine/docs/java/memcache/usingjcache.html
69. URL Fetch Java API GAE permite realizar conexiones HTTP y HTTPS a travs del servicio URL Fetch, que en el caso de GAE for Java se implementa mediante la clase java.net.URLConnection La funcionalidad que da es: Acceso sencillo a los contenidos de una pgina mediante java.net.URL y el mtodo openStream() El mtodo openConnection() de java.net.URL devuelve una instancia de HttpURLConnection, sobre la que se puede hacer getInputStream() y getOutputStream() Se pueden cambiar propiedades de la conexin como: Aadir cabeceras: connection.setRequestProperty("X-MyApp-Version", "2.7.3"); Modificar el hecho de que las peticiones se redirijan directamente: connection.setRequestProperty("X-MyApp-Version", "2.7.3"); Ms detalles en: http://code.google.com/intl/en/appengine/docs/java/urlfetch/usingjavanet.html
Mail Java API Una aplicacin en AppEngine puede enviar mensajes en representacin del administrador de la pgina o de usuarios autorizados con cuentas Google La Mail Service Java API hace uso de javax.mail Se puede configurar tu aplicacin para recibir mensajes en una direccin con el formato string@appid.appspotmail.com Cuando una aplicacin se ejecuta en el servidor de desarrollo, el mensaje enviado se imprime en el log, no se enva
72. Recibiendo un Mensaje Los pasos a seguir son: Configurar tu aplicacin para ser receptora de email en la direccin: 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 direccin: /_ah/mail/<address> <servlet> <servlet-name>mailhandler</servlet-name> <servlet-class>MailHandlerServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>mailhandler</servlet-name> <url-pattern>/_ah/mail/*</url-pattern> </servlet-mapping> <security-constraint> <web-resource-collection> <url-pattern>/_ah/mail/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint>
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 aplicacin Java puede crear una cola configurada en el fichero de configuracin WEB-INF/queue.xml Para encolar una tarea, hay que obtener una instancia de Queue usando una QueueFactory y luego invocar el mtodo add() Puedes obtener una cola por nombre declarada en el fichero queue.xml o la cola por defecto con el mtodo getDefaultQueue() Se puede aadir una tarea a la cola pasando una instancia de TaskOptions al mtodo add() Se invocar un servlet que ser quien ejecute la tarea encolada (ver ejemplo siguiente trasparencia) Espacio de nombres en versin beta: com.google.appengine.api.labs.taskqueue
75. Ejemplo de TaskQueue API El siguiente ejemplo muestra cmo aadir 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 das, es decir, la frecuencia con la que las tareas encoladas seran procesadas: <queue- entries> <queue> <name>default</name> <rate>1/s</rate> </queue> <queue> <name>mail-queue</name> <rate>2000/d</rate> <bucket-size>10</bucket- size> </queue> <queue> <name>background- processing</name> <rate>5/s</rate> </queue></queue-entries>
Combinando Struts2 y GAE Revisar ejemplo: struts2tutorial Modificaciones a realizar en la distribucin de struts2tutorial: Reimplementar la clase freemarker.core.TextBlock Inicializar a null el SecurityManager de OgnlRuntime Explicacin de cmo hacerlo en: http://whyjava.wordpress.com/2009/08/30/creating-struts2-application-on-google- app-engine-gae/
Plugin for Eclipse for Java Instrucciones en: http://code.google.com/eclipse/docs/download.html Descarga Eclipse Galileo for Java Developers de: http://www.eclipse.org/downloads/
Importacin y Exportacin de Datos Se pueden acceder a datos detrs de tu Intranet desde una aplicacin 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.ht ml 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 AppEngine for Business Las aplicaciones generadas con AppEngine for Business usan las APIs de Java y Python, pero permiten acceder al desarrollador a capacidades especiales (premium): Acceso a SSL y SQL Tendrn un coste adicional Mas informacin en: http://code.google.com/appengine/business/
El servicio tiene varias limitaciones: Solo hasta recientemente no todo el mundo poda acceder a l Es gratis durante el periodo de pruebas, pero con lmites de uso: 500 MB de almacenamiento, 200 millones de megaciclos/da y 10 Gb de ancho de banda Google cobra para webs que requieren alta escalabilidad Existen escasas aplicaciones comerciales desarrolladas en esta plataforma Repositorio de ejemplos: http://appgallery.appspot.com/ VOSAO CMS - http://www.vosao.org/
Los desarrolladores solamente tienen acceso de lectura al sistema de ficheros de AppEngine Solamente se puede ejecutar cdigo a partir de una peticin HTTP Solamente se puede subir cdigo puramente Python (resuelto con soporte Java) No se puede descargar o ejecutar scripts en su base de datos (remote_api) Las aplicaciones deben ser escritas en Python o Java
Google AppEngine es una plataforma mucho ms acoplada y menos flexible Si quieres hacer uso de BigTable tienes que escribir y desplegar un script de Python a su servidor de aplicaciones ofreciendo una interfaz web accesible a BigTable (resuelto parcialmente)
Referencias Google AppEngine http://code.google.com/appengine/