Die Google App Engine (GAE) zählt zu den Cloud-Computing-Plattformen. Beim Cloud Computing werden Anwendungen auf entfernten Servern gehostet und ausgeführt. Die wichtigsten Vorteile sind: Es muss keine eigene IT vorhanden sein und gewartet werden, die Anwendung kann bei Bedarf ("On-Demand") leicht hoch skaliert werden und es werden optimale Internet-Zugriffsgeschwindigkeiten angeboten.
Es gibt verschiedene Kategorisierungen für Cloud-Computing-Systeme, zum Beispiel die beiden folgenden.
Kategorisierung nach Zugänglichkeit:
Private Cloud | Nur für bestimmte Anwender nutzbar, meistens nur innerhalb einer Firma. Kann bereits wesentliche Kosteneinsparungen bringen. Daten müssen nicht außer Haus gegeben werden. Beispiel: Red Hat CloudForms |
Public Cloud | Öffentlich zugänglich und gegen Bezahlung nutzbar. Bietet wesentlich größeres Sparpotenzial. Könnte wegen der Datenüberlassung kritischer sein. Beispiele: Amazon EC2, Red Hat OpenShift Cloud, Google App Engine (GAE), Microsoft Azure |
Kategorisierung nach Architekturebene bzw. Serviceart:
Software as a Service (SaaS) |
Software wird als Dienstleistung basierend auf Internettechniken angeboten. Beispiele: Web-E-Mail-Dienste, Google Apps, Salesforce CRM, Microsoft Office 365 |
Platform as a Service (PaaS) |
Eine integrierte Laufzeit- (und evtl. auch Entwicklungs-)umgebung wird als Dienst für eigene Programme zur Verfügung gestellt. In der Regel gibt es bestimmte Einschränkungen (z.B. Programmiersprache). Beispiele: Red Hat OpenShift, Google App Engine (GAE), Heroku, Microsoft Azure |
Infrastructure as a Service (IaaS) |
Eine Rechnerinfrastruktur wird als Dienst zur Verfügung gestellt. Meistens können verschiedene Betriebssysteme und beliebige Programmiersprachen eingesetzt werden. Beispiel: Amazon EC2 |
Google App Engine (GAE) | Amazon EC2 (Elastic Compute Cloud) | |
---|---|---|
Cloud-Typ | Platform as a Service (PaaS) | Infrastructure as a Service (IaaS) |
Programmiersprachen | Java und Python | beliebig |
Deployment | bei Java: als WAR | als Amazon Machine Image (AMI) |
Java-APIs | z.B. Servlets, JCache, JavaMail | beliebig |
Datenbank | BigTable, JPA, JDO | SimpleDB, S3 (Simple Storage Service) |
Asynchrones Messaging | Task Queue API | SQS (Simple Queue Service) |
Proprietäre Services | Google Accounts, GWT (Google Web Toolkit), Cron-Job-Scheduling |
AWS (Amazon Web Services) |
Einschränkungen | viele Einschränkungen, z.B. Programmiersprache, Middleware, GQL-DB, kein Datei-Schreiben, keine Sockets, keine eigenen Threads, Timeout-Begrenzung |
fast keine Einschränkungen |
Technischer Einstieg, Tools | kostenlose Basisfunktionalität, sehr einfacher Einstieg, gute Entwicklerunterstützung, gutes Eclipse-Plug-in, GAE Dashboard, Programmierbeispiele siehe unten |
höhere Einstiegshürde, ElasticFox |
Skalierung, Clustering, Load Balancing, Failover | übernimmt die Google-Infrastruktur | in der Verantwortung des Entwicklers (eventuell SysAdmin benötigt) |
Wählen Sie in Eclipse: 'File' | 'New' | 'Project...' | '[+] Google' | 'Web Application Project' | 'Next' (oder klicken Sie alternativ auf das blaue 'New Web Application Project'-Icon in der Toolbar). Tragen Sie im 'New Web Application Project'-Dialog ein:
Project name: | GAE-HelloWorld |
Package: | helloworld |
Use Google Web Toolkit: | nein |
Use Google App Engine: | ja |
Finish |
Ihre Verzeichnisstruktur sieht jetzt im Wesentlichen folgendermaßen aus (kontrollieren Sie es mit "tree /F"):
[\MeinWorkspace] '- [GAE-HelloWorld] |- [.settings] | '- com.google.appengine.eclipse.core.prefs |- [src] | |- [helloworld] | | '- GAE_HelloWorldServlet.java | |- [META-INF] | | '- jdoconfig.xml | '- log4j.properties '- [war] '- [WEB-INF] | |- [classes] | | |- [helloworld] | | | '- GAE_HelloWorldServlet.class | | |- [META-INF] | | | '- jdoconfig.xml | | '- log4j.properties | |- [lib] | | '- ...jar | |- appengine-web.xml | |- logging.properties | '- web.xml '- index.html
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste auf den 'GAE-HelloWorld'-Projektnamen
und wählen Sie 'Run As' | 'Web Application'.
In der Console erscheint: "The server is running at http://localhost:8080/".
Öffnen Sie im war/WEB-INF-Verzeichnis die Konfigurationsdatei appengine-web.xml. Ersetzen Sie die Zeile
<application></application>
durch
<application>!!meineGoogleApplicationID!!</application>
Statt !!meineGoogleApplicationID!! setzen Sie die ID ein, die Sie beim Sign up gewählt haben.
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste auf den 'GAE-HelloWorld'-Projektnamen
und wählen Sie 'Google' | 'Deploy to App Engine'.
Tragen Sie Ihre bei Google angegebene Email-Adresse und Ihr Password ein.
In der Console erscheint: "Deployment completed successfully".
JPA (Java Persistence API) ist der aktuelle Java-Standard für Persistenz.
JPA vereint viele Vorteile von Hibernate, TopLink und JDO.
Siehe hierzu auch:
java-jpa.htm,
The Java Persistence API - A Simpler Programming Model for Entity Persistence und
JPA API.
Beachten Sie die Einschränkungen zu JPA durch die Google App Engine unter Using JPA with App Engine: Unsupported Features of JPA.
Wählen Sie in Eclipse: 'File' | 'New' | 'Project...' | '[+] Google' | 'Web Application Project' | 'Next' (oder klicken Sie alternativ auf das blaue 'New Web Application Project'-Icon in der Toolbar). Tragen Sie im 'New Web Application Project'-Dialog ein:
Project name: | GAE-JPA-Webanwendung |
Package: | jpaapp |
Use Google Web Toolkit: | nein |
Use Google App Engine: | ja |
Finish |
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste unter src auf das Package jpaapp und wählen Sie 'New' | 'Class' | 'Name: EintragDO' | 'Finish'. Ersetzen Sie den Inhalt von EintragDO.java durch:
package jpaapp; import java.text.SimpleDateFormat; import java.util.Date; import javax.persistence.*; @Entity public class EintragDO { private static final SimpleDateFormat YYYYMMDD_HHMM = new SimpleDateFormat( "yyyy-MM-dd HH:mm" ); @Id @GeneratedValue( strategy = GenerationType.IDENTITY ) private Long id; private String eintrag; private String datum; private String ip; public EintragDO( String eintrag, String ip ) { this.eintrag = eintrag; this.datum = YYYYMMDD_HHMM.format( new Date() ); this.ip = ip; } public Long getId() { return id; } public String getEintrag() { return eintrag; } public String getDatum() { return datum; } public String getIp() { return ip; } }
Erläuterungen zu den verwendeten Annotationen finden Sie unter @Entity, @Id und @GeneratedValue.
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste unter src auf das Package jpaapp und wählen Sie 'New' | 'Class' | 'Name: EintragDAO' | 'Finish'. Ersetzen Sie den Inhalt von EintragDAO.java durch:
package jpaapp; import java.util.*; import javax.persistence.*; // Data Access Object: public class EintragDAO { private static final EntityManagerFactory EMF = Persistence.createEntityManagerFactory( "transactions-optional" ); // Fuege Eintrag hinzu: @SuppressWarnings( "unchecked" ) public static void fuegeEintragHinzu( String eintrag, String ip ) { EntityManager em = EMF.createEntityManager(); try { // Laenge der Liste begrenzen: Query query = em.createQuery( "SELECT e from " + EintragDO.class.getName() + " e" ); List<EintragDO> eintraege = (List<EintragDO>) query.getResultList(); if( eintraege != null && eintraege.size() >= 20 ) em.remove( eintraege.get( 0 ) ); // Neuen Eintrag hinzufuegen: EintragDO eintragDO = new EintragDO( eintrag, ip ); em.persist( eintragDO ); } finally { em.close(); } } // Lies Eintraege: @SuppressWarnings( "unchecked" ) public static List<EintragDO> liesEintraege() { EntityManager em = EMF.createEntityManager(); try { Query query = em.createQuery( "SELECT e from " + EintragDO.class.getName() + " e" ); // Decoupling wegen lazy Loading: return new ArrayList<EintragDO>( query.getResultList() ); } finally { em.close(); } } }
Erläuterungen zu den verwendeten JPA-Klassen finden Sie unter java-jpa.htm und JPA API.
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste unter src auf das Verzeichnis META-INF und wählen Sie 'New' | 'File' | 'File name: persistence.xml' | 'Finish'. Ersetzen Sie den Inhalt von persistence.xml durch:
<?xml version="1.0" encoding="UTF-8" ?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="transactions-optional"> <provider>org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider</provider> <properties> <property name="datanucleus.NontransactionalRead" value="true" /> <property name="datanucleus.NontransactionalWrite" value="true" /> <property name="datanucleus.ConnectionURL" value="appengine" /> </properties> </persistence-unit> </persistence>
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste auf das Verzeichnis war und wählen Sie 'New' | 'File' | 'File name: eintrag.jsp' | 'Finish'. Ersetzen Sie den Inhalt von eintrag.jsp durch:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.util.List" %> <%@ page import="jpaapp.*" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Einträge</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta> </head> <body> <h2>Einträge</h2> <% String neuerEintrag = request.getParameter( "eintrag" ); if( neuerEintrag != null && neuerEintrag.length() > 0 ) EintragDAO.fuegeEintragHinzu( neuerEintrag, request.getRemoteHost() ); List<EintragDO> eintraege = EintragDAO.liesEintraege(); if( eintraege != null && eintraege.size() > 0 ) { %> <table border=0 cellspacing=3 cellpadding=2> <tr bgcolor="#EBEEEE"><td>ID</td><td>Eintrag</td><td>Datum</td><td>IP</td></tr> <% for( EintragDO eintrag : eintraege ) { %> <tr><td bgcolor="#EBEEEE"><%= eintrag.getId() %></td> <td><%= eintrag.getEintrag() %></td> <td><%= eintrag.getDatum() %> h</td> <td><%= eintrag.getIp() %></td></tr> <% } %> </table> <% } %> <br> <p> Bitte Eintrag erstellen und 'Speichern' betätigen:</p> <form method="post" accept-charset="utf-8"> <input type="text" name="eintrag" id="eintrag" size="60" maxlength="60" /> <input type="submit" value="Speichern" /> </form> </body> </html>
Öffnen Sie im war/WEB-INF-Verzeichnis die Datei web.xml und ersetzen Sie den Inhalt durch:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"> <welcome-file-list> <welcome-file>eintrag.jsp</welcome-file> </welcome-file-list> </web-app>
Ihre Verzeichnisstruktur sieht jetzt im Wesentlichen folgendermaßen aus (kontrollieren Sie es mit "tree /F"):
[\MeinWorkspace] '- [GAE-JPA-Webanwendung] |- [.settings] | '- com.google.appengine.eclipse.core.prefs |- [src] | |- [jpaapp] | | |- EintragDAO.java | | '- EintragDO.java | |- [META-INF] | | '- persistence.xml | '- log4j.properties '- [war] '- [WEB-INF] | |- [appengine-generated] | | '- ... | |- [classes] | | '- ... | |- [lib] | | '- ... | |- appengine-web.xml | |- logging.properties | '- web.xml '- eintrag.jsp
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste auf den 'GAE-JPA-Webanwendung'-Projektnamen
und wählen Sie 'Run As' | 'Web Application'.
In der Console erscheint: "The server is running at http://localhost:8080/".
Öffnen Sie im war/WEB-INF-Verzeichnis die Konfigurationsdatei appengine-web.xml. Ersetzen Sie die Zeile
<application></application>
durch
<application>!!meineGoogleApplicationID!!</application>
Statt !!meineGoogleApplicationID!! setzen Sie die ID ein, die Sie beim Sign up gewählt haben.
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste auf den 'GAE-JPA-Webanwendung'-Projektnamen
und wählen Sie 'Google' | 'Deploy to App Engine'.
Tragen Sie Ihre bei Google angegebene Email-Adresse und Ihr Password ein.
In der Console erscheint: "Deployment completed successfully".
Verwenden Sie JDO (Java Data Objects) nur, wenn Sie besondere Gründe hierfür haben. Ansonsten sollten Sie den verbesserten Nachfolger JPA verwenden. Zu JPA siehe das Programmierbeispiel Persistenz mit JPA.
Wählen Sie in Eclipse: 'File' | 'New' | 'Project...' | '[+] Google' | 'Web Application Project' | 'Next' (oder klicken Sie alternativ auf das blaue 'New Web Application Project'-Icon in der Toolbar). Tragen Sie im 'New Web Application Project'-Dialog ein:
Project name: | GAE-JDO-Webanwendung |
Package: | jdoapp |
Use Google Web Toolkit: | nein |
Use Google App Engine: | ja |
Finish |
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste unter src auf das Package jdoapp und wählen Sie 'New' | 'Class' | 'Name: EintragDO' | 'Finish'. Ersetzen Sie den Inhalt von EintragDO.java durch:
package jdoapp; import java.text.SimpleDateFormat; import java.util.Date; import javax.jdo.annotations.*; @PersistenceCapable( identityType = IdentityType.APPLICATION ) public class EintragDO { private static final SimpleDateFormat YYYYMMDD_HHMM = new SimpleDateFormat( "yyyy-MM-dd HH:mm" ); @PrimaryKey @Persistent( valueStrategy = IdGeneratorStrategy.IDENTITY ) private Long id; @Persistent private String eintrag; @Persistent private String datum; @Persistent private String ip; public EintragDO( String eintrag, String ip ) { this.eintrag = eintrag; this.datum = YYYYMMDD_HHMM.format( new Date() ); this.ip = ip; } public Long getId() { return id; } public String getEintrag() { return eintrag; } public String getDatum() { return datum; } public String getIp() { return ip; } }
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste unter src auf das Package jdoapp und wählen Sie 'New' | 'Class' | 'Name: EintragDAO' | 'Finish'. Ersetzen Sie den Inhalt von EintragDAO.java durch:
package jdoapp; import java.util.*; import javax.jdo.*; // Data Access Object: public class EintragDAO { private static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory( "transactions-optional" ); // Fuege Eintrag hinzu: @SuppressWarnings( "unchecked" ) public static void fuegeEintragHinzu( String eintrag, String ip ) { PersistenceManager pm = PMF.getPersistenceManager(); try { // Laenge der Liste begrenzen: Query query = pm.newQuery( EintragDO.class ); List<EintragDO> eintraege = (List<EintragDO>) query.execute(); if( eintraege != null && eintraege.size() >= 20 ) pm.deletePersistent( eintraege.get( 0 ) ); // Neuen Eintrag hinzufuegen: EintragDO eintragDO = new EintragDO( eintrag, ip ); pm.makePersistent( eintragDO ); } finally { pm.close(); } } // Lies Eintraege: @SuppressWarnings( "unchecked" ) public static List<EintragDO> liesEintraege() { PersistenceManager pm = PMF.getPersistenceManager(); try { Query query = pm.newQuery( EintragDO.class ); // Decoupling wegen lazy Loading: return new ArrayList<EintragDO>( (Collection) query.execute() ); } finally { pm.close(); } } }
Öffnen Sie im Eclipse Project Explorer unter src das Verzeichnis META-INF und öffnen Sie darin die bereits erstellte Konfigurationsdatei jdoconfig.xml. Sie muss folgenden Inhalt haben:
<?xml version="1.0" encoding="utf-8"?> <jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig"> <persistence-manager-factory name="transactions-optional"> <property name="javax.jdo.PersistenceManagerFactoryClass" value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/> <property name="javax.jdo.option.ConnectionURL" value="appengine"/> <property name="javax.jdo.option.NontransactionalRead" value="true"/> <property name="javax.jdo.option.NontransactionalWrite" value="true"/> <property name="javax.jdo.option.RetainValues" value="true"/> <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/> </persistence-manager-factory> </jdoconfig>
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste auf das Verzeichnis war und wählen Sie 'New' | 'File' | 'File name: eintrag.jsp' | 'Finish'. Ersetzen Sie den Inhalt von eintrag.jsp durch:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.util.List" %> <%@ page import="jdoapp.*" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Einträge</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta> </head> <body> <h2>Einträge</h2> <% String neuerEintrag = request.getParameter( "eintrag" ); if( neuerEintrag != null && neuerEintrag.length() > 0 ) EintragDAO.fuegeEintragHinzu( neuerEintrag, request.getRemoteHost() ); List<EintragDO> eintraege = EintragDAO.liesEintraege(); if( eintraege != null && eintraege.size() > 0 ) { %> <table border=0 cellspacing=3 cellpadding=2> <tr bgcolor="#EBEEEE"><td>ID</td><td>Eintrag</td><td>Datum</td><td>IP</td></tr> <% for( EintragDO eintrag : eintraege ) { %> <tr><td bgcolor="#EBEEEE"><%= eintrag.getId() %></td> <td><%= eintrag.getEintrag() %></td> <td><%= eintrag.getDatum() %> h</td> <td><%= eintrag.getIp() %></td></tr> <% } %> </table> <% } %> <br> <p> Bitte Eintrag erstellen und 'Speichern' betätigen:</p> <form method="post" accept-charset="utf-8"> <input type="text" name="eintrag" id="eintrag" size="60" maxlength="60" /> <input type="submit" value="Speichern" /> </form> </body> </html>
Öffnen Sie im war/WEB-INF-Verzeichnis die Datei web.xml und ersetzen Sie den Inhalt durch:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"> <welcome-file-list> <welcome-file>eintrag.jsp</welcome-file> </welcome-file-list> </web-app>
Ihre Verzeichnisstruktur sieht jetzt im Wesentlichen folgendermaßen aus (kontrollieren Sie es mit "tree /F"):
[\MeinWorkspace] '- [GAE-JDO-Webanwendung] |- [.settings] | '- com.google.appengine.eclipse.core.prefs |- [src] | |- [jdoapp] | | |- EintragDAO.java | | '- EintragDO.java | |- [META-INF] | | '- jdoconfig.xml | '- log4j.properties '- [war] '- [WEB-INF] | |- [appengine-generated] | | '- ... | |- [classes] | | '- ... | |- [lib] | | '- ... | |- appengine-web.xml | |- logging.properties | '- web.xml '- eintrag.jsp
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste auf den 'GAE-JDO-Webanwendung'-Projektnamen
und wählen Sie 'Run As' | 'Web Application'.
In der Console erscheint: "The server is running at http://localhost:8080/".
Öffnen Sie im war/WEB-INF-Verzeichnis die Konfigurationsdatei appengine-web.xml. Ersetzen Sie die Zeile
<application></application>
durch
<application>!!meineGoogleApplicationID!!</application>
Statt !!meineGoogleApplicationID!! setzen Sie die ID ein, die Sie beim Sign up gewählt haben.
Klicken Sie im Eclipse Project Explorer mit der rechten Maustaste auf den 'GAE-JDO-Webanwendung'-Projektnamen
und wählen Sie 'Google' | 'Deploy to App Engine'.
Tragen Sie Ihre bei Google angegebene Email-Adresse und Ihr Password ein.
In der Console erscheint: "Deployment completed successfully".