Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

5

Partager

Gaelyk: Lightweight Groovy on the Google App Engine

Gaelyk is a lightweight Groovy web application framework built specifically for the Google App Engine. It provides a fast, easy way to build simply applications in Groovy and host them for free on the GAE.

Livres associés

Gratuit avec un essai de 30 jours de Scribd

Tout voir

Gaelyk: Lightweight Groovy on the Google App Engine

  1. 1. Lightweight on the by Tim Berglund
  2. 2. Tell me about aGreat Application Language
  3. 3. Tell me a Happy Tale of Deployment
  4. 4. and Make it Fast
  5. 5. Tell me about the Googl eApp Engine
  6. 6. An App Server
  7. 7. In the CLoud
  8. 8. Google Infrastructure
  9. 9. Usually Free!
  10. 10. Quotas http://code.google.com/appengine/docs/quotas.html
  11. 11. Quotas http://code.google.com/appengine/docs/quotas.html
  12. 12. Pricing
  13. 13. Languages
  14. 14. Languages
  15. 15. Languages
  16. 16. Languages
  17. 17. Services
  18. 18. Services It’s an app server
  19. 19. Services With a few extra features
  20. 20. Services
  21. 21. Services Datastore
  22. 22. Services Datastore Authentication
  23. 23. Services Datastore Authentication Caching
  24. 24. Services Datastore Authentication Caching XMPP
  25. 25. Services Datastore Authentication Caching XMPP Email
  26. 26. Services Datastore Task Queue Authentication Caching XMPP Email
  27. 27. Services Datastore Task Queue Authentication Image API Caching XMPP Email
  28. 28. Services Datastore Task Queue Authentication Image API Caching URL Fetching XMPP Email
  29. 29. Services Datastore Task Queue Authentication Image API Caching URL Fetching XMPP OAuth Email
  30. 30. Services Datastore Task Queue Authentication Image API Caching URL Fetching XMPP OAuth Email Blobstore
  31. 31. But It’s not Perfect
  32. 32. Limitations
  33. 33. Limitations The JDK whitelist
  34. 34. Limitations The JDK whitelist http://code.google.com/appengine/docs/java/jrewhitelist.html
  35. 35. Limitations The JDK whitelist http://code.google.com/appengine/docs/java/jrewhitelist.html No Hibernate
  36. 36. Limitations The JDK whitelist http://code.google.com/appengine/docs/java/jrewhitelist.html No Hibernate Only JPA and JDO
  37. 37. Limitations The JDK whitelist http://code.google.com/appengine/docs/java/jrewhitelist.html No Hibernate Only JPA and JDO Grails is limited
  38. 38. Limitations The JDK whitelist http://code.google.com/appengine/docs/java/jrewhitelist.html No Hibernate Only JPA and JDO Grails is limited Performance problems?
  39. 39. Tell me about
  40. 40. Groovy-based
  41. 41. Groovy-based Lightweight
  42. 42. Groovy-based Lightweight Page-centric
  43. 43. Groovy-based Lightweight Page-centric Tightly coupled to the Google App Engine
  44. 44. Groovy-based Lightweight Page-centric Tightly coupled to the Google App Engine A better GAE than the GAE
  45. 45. Setting up Gaelyk
  46. 46. Serving Content
  47. 47. Serving Content
  48. 48. Serving Content Static content (like in a WAR)
  49. 49. Serving Content Static content (like in a WAR) Groovy templates
  50. 50. Templates <% include '/WEB-INF/includes/header.gtpl' %> <h1>Look Up an Artist</h1> <form action="/artistLookup.groovy" method="POST"> <input type="text" size="50" name="artist"/> <input type="submit" value="Lookup"/> </form> <ul> <% request.artists.each { artist -> %> <li>${artist.name}</li> <% } %> </ul> <% include '/WEB-INF/includes/footer.gtpl' %>
  51. 51. Templates <% include '/WEB-INF/includes/header.gtpl' %> <h1>Look Up an Artist</h1> <form action="/artistLookup.groovy" method="POST"> <input type="text" size="50" name="artist"/> <input type="submit" value="Lookup"/> </form> <ul> <% request.artists.each { artist -> %> <li>${artist.name}</li> <% } %> </ul> <% include '/WEB-INF/includes/footer.gtpl' %>
  52. 52. Templates <% include '/WEB-INF/includes/header.gtpl' %> <h1>Look Up an Artist</h1> <form action="/artistLookup.groovy" method="POST"> <input type="text" size="50" name="artist"/> <input type="submit" value="Lookup"/> </form> <ul> <% request.artists.each { artist -> %> <li>${artist.name}</li> <% } %> </ul> <% include '/WEB-INF/includes/footer.gtpl' %>
  53. 53. Templates <% include '/WEB-INF/includes/header.gtpl' %> <h1>Look Up an Artist</h1> <form action="/artistLookup.groovy" method="POST"> <input type="text" size="50" name="artist"/> <input type="submit" value="Lookup"/> </form> <ul> <% request.artists.each { artist -> %> <li>${artist.name}</li> <% } %> </ul> <% include '/WEB-INF/includes/footer.gtpl' %>
  54. 54. Templates <% include '/WEB-INF/includes/header.gtpl' %> <h1>Look Up an Artist</h1> <form action="/artistLookup.groovy" method="POST"> <input type="text" size="50" name="artist"/> <input type="submit" value="Lookup"/> </form> <ul> <% request.artists.each { artist -> %> <li>${artist.name}</li> <% } %> </ul> <% include '/WEB-INF/includes/footer.gtpl' %>
  55. 55. Templates
  56. 56. Templates Lightweight, Groovy JSPs
  57. 57. Templates Lightweight, Groovy JSPs Downside: Scriptlets
  58. 58. Templates Lightweight, Groovy JSPs Downside: Scriptlets Request attributes bound from Groovlets
  59. 59. Groovlets import java.net.URLEncoder if(params.artist) { def response = urlFetch.fetch(new URL("http://musicbrainz.org/ ws/1/artist/?type=xml&name=${URLEncoder.encode(params.artist)}")) def text = new String(response.content) def xml = new XmlSlurper().parseText(text) request.artists = xml.'artist-list'.artist } else { request.artists = [] } forward '/artistLookup.gtpl'
  60. 60. Groovlets
  61. 61. Groovlets Groovy script, meet Servlet
  62. 62. Groovlets Groovy script, meet Servlet Intrinsic variables
  63. 63. Groovlets Groovy script, meet Servlet Intrinsic variables Forwarding
  64. 64. Groovlets Groovy script, meet Servlet Intrinsic variables Forwarding Redirecting
  65. 65. Groovlets Groovy script, meet Servlet Intrinsic variables Forwarding Redirecting MarkupBuilder
  66. 66. import java.net.URLEncoder if(params.artist) { def response = urlFetch.fetch(new URL("http:// musicbrainz.org/ws/1/artist/?type=xml&name=$ {URLEncoder.encode(params.artist)}")) def text = new String(response.content) def xml = new XmlSlurper().parseText(text) request.artists = xml.'artist-list'.artist } else { request.artists = [] } forward '/artistLookup.gtpl'
  67. 67. import java.net.URLEncoder if(params.artist) { def response = urlFetch.fetch(new URL("http:// musicbrainz.org/ws/1/artist/?type=xml&name=$ {URLEncoder.encode(params.artist)}")) def text = new String(response.content) def xml = new XmlSlurper().parseText(text) request.artists = xml.'artist-list'.artist } else { request.artists = [] } forward '/artistLookup.gtpl'
  68. 68. import java.net.URLEncoder if(params.artist) { def response = urlFetch.fetch(new URL("http:// musicbrainz.org/ws/1/artist/?type=xml&name=$ {URLEncoder.encode(params.artist)}")) def text = new String(response.content) def xml = new XmlSlurper().parseText(text) request.artists = xml.'artist-list'.artist } else { request.artists = [] } forward '/artistLookup.gtpl'
  69. 69. import java.net.URLEncoder if(params.artist) { def response = urlFetch.fetch(new URL("http:// musicbrainz.org/ws/1/artist/?type=xml&name=$ {URLEncoder.encode(params.artist)}")) def text = new String(response.content) def xml = new XmlSlurper().parseText(text) request.artists = xml.'artist-list'.artist } else { request.artists = [] } forward '/artistLookup.gtpl'
  70. 70. import com.google.appengine.api.datastore.* import static com.google.appengine.api.datastore.FetchOption if(!user) { redirect users.createLoginURL(request.requestURL.toString( return } def query = new Query("project") query.addSort("dateCreated", Query.SortDirection.ASCENDING) PreparedQuery preparedQuery = datastore.prepare(query) request.projects = preparedQuery.asList( withOffset(0) ) forward "/WEB-INF/views/project/list.gtpl"
  71. 71. import com.google.appengine.api.datastore.* import static com.google.appengine.api.datastore.FetchOption if(!user) { redirect users.createLoginURL(request.requestURL.toString( return } def query = new Query("project") query.addSort("dateCreated", Query.SortDirection.ASCENDING) PreparedQuery preparedQuery = datastore.prepare(query) request.projects = preparedQuery.asList( withOffset(0) ) forward "/WEB-INF/views/project/list.gtpl"
  72. 72. import com.google.appengine.api.datastore.* import static com.google.appengine.api.datastore.FetchOption if(!user) { redirect users.createLoginURL(request.requestURL.toString( return } def query = new Query("project") query.addSort("dateCreated", Query.SortDirection.ASCENDING) PreparedQuery preparedQuery = datastore.prepare(query) request.projects = preparedQuery.asList( withOffset(0) ) forward "/WEB-INF/views/project/list.gtpl"
  73. 73. import com.google.appengine.api.datastore.* import static com.google.appengine.api.datastore.FetchOption if(!user) { redirect users.createLoginURL(request.requestURL.toString( return } def query = new Query("project") query.addSort("dateCreated", Query.SortDirection.ASCENDING) PreparedQuery preparedQuery = datastore.prepare(query) request.projects = preparedQuery.asList( withOffset(0) ) forward "/WEB-INF/views/project/list.gtpl"
  74. 74. import com.google.appengine.api.datastore.* import static com.google.appengine.api.datastore.FetchOption if(!user) { redirect users.createLoginURL(request.requestURL.toString( return } def query = new Query("project") query.addSort("dateCreated", Query.SortDirection.ASCENDING) PreparedQuery preparedQuery = datastore.prepare(query) request.projects = preparedQuery.asList( withOffset(0) ) forward "/WEB-INF/views/project/list.gtpl"
  75. 75. import com.google.appengine.api.datastore.* import static com.google.appengine.api.datastore.FetchOption if(!user) { redirect users.createLoginURL(request.requestURL.toString( return } def query = new Query("project") query.addSort("dateCreated", Query.SortDirection.ASCENDING) PreparedQuery preparedQuery = datastore.prepare(query) request.projects = preparedQuery.asList( withOffset(0) ) forward "/WEB-INF/views/project/list.gtpl"
  76. 76. URL Mapping
  77. 77. URL Mapping Templates in war/*.gtpl
  78. 78. URL Mapping Templates in war/*.gtpl Groovlets in war/WEB-INF/groovy/*.groovy
  79. 79. URL Mapping Templates in war/*.gtpl Groovlets in war/WEB-INF/groovy/*.groovy Pretty URLs with war/WEB-INF/routes.groovy
  80. 80. The Datastore
  81. 81. The Datastore
  82. 82. The Datastore Google’s BigTable infrastructure
  83. 83. The Datastore Google’s BigTable infrastructure Schemaless
  84. 84. The Datastore Google’s BigTable infrastructure Schemaless Named entities (property bundles)
  85. 85. The Datastore Google’s BigTable infrastructure Schemaless Named entities (property bundles) Indexed, queryable, sortable
  86. 86. The Datastore Google’s BigTable infrastructure Schemaless Named entities (property bundles) Indexed, queryable, sortable Transactional
  87. 87. The Datastore Google’s BigTable infrastructure Schemaless Named entities (property bundles) Indexed, queryable, sortable Transactional Great Groovy wrapper
  88. 88. Datastore Indexes
  89. 89. Datastore Indexes Automatically generated by default
  90. 90. Datastore Indexes Automatically generated by default Override in WEB-INF/datastore-indexes.xml
  91. 91. Datastore Indexes Automatically generated by default Override in WEB-INF/datastore-indexes.xml <?xml version="1.0" encoding="utf-8"?> <datastore-indexes   autoGenerate="true">     <datastore-index kind="Employee" ancestor="false">         <property name="lastName" direction="asc" />         <property name="hireDate" direction="desc" />     </datastore-index>     <datastore-index kind="Project" ancestor="false">         <property name="dueDate" direction="asc" />     </datastore-index> </datastore-indexes>
  92. 92. Tell me about Other Services
  93. 93. Email in Java
  94. 94. Email with Gaelyk mail.send sender: 'story-admin@augusttechgroup.com', to: 'tlberglund@gmail.com', subject: 'Story Complete', textBody: "A story you edited has increased in priority. Check it out."
  95. 95. Inbound Email
  96. 96. Inbound Email Enable in appengine-web.xml
  97. 97. Inbound Email Enable in appengine-web.xml Enable built-in servlet in web.xml
  98. 98. Inbound Email Enable in appengine-web.xml Enable built-in servlet in web.xml email.groovy Groovlet
  99. 99. Inbound Email Enable in appengine-web.xml Enable built-in servlet in web.xml email.groovy Groovlet The “message” intrinsic variable
  100. 100. Memcache in Java
  101. 101. Memcache with Gaelyk def countryFr = new Country(name: 'France') memcache['FR'] = countryFr if ('FR' in memcache) { countryFromCache = memcache['FR'] }
  102. 102. URL Fetch in Java
  103. 103. URL Fetch with Gaelyk def response = urlFetch.fetch(new URL("http://example.com")) def text = new String(response.content)
  104. 104. Task Queues queue.add countdownMillis: 10000, url: '/task/emailTaskList', taskName: 'Email current story assignments', method: 'PUT', params: [date: new Date()]
  105. 105. Task Queues
  106. 106. Task Queues Timed HTTP requests
  107. 107. Task Queues Timed HTTP requests Configure in war/WEB-INF/queue.xml
  108. 108. Task Queues Timed HTTP requests Configure in war/WEB-INF/queue.xml http://code.google.com/appengine/docs/java/config/queue.html
  109. 109. Task Queues Timed HTTP requests Configure in war/WEB-INF/queue.xml http://code.google.com/appengine/docs/java/config/queue.html Can update without redeploying
  110. 110. Task Queues Timed HTTP requests Configure in war/WEB-INF/queue.xml http://code.google.com/appengine/docs/java/config/queue.html Can update without redeploying Can be secured
  111. 111. XMPP
  112. 112. XMPP User notification
  113. 113. XMPP User notification XML payloads for distributed communication
  114. 114. XMPP User notification XML payloads for distributed communication Send messages with a Groovier API
  115. 115. XMPP User notification XML payloads for distributed communication Send messages with a Groovier API Receive messages through a servlet
  116. 116. XMPP Sending in Java
  117. 117. XMPP Sending with Gaelyk
  118. 118. XMPP Sending with Gaelyk def recipient = 'tlberglund@gmail.com' if (xmpp.getPresence(recipient).isAvailable()) { def status = xmpp.send(to: recipient, body: "Glad you're into Gaelyk!") if (!status.isSuccessful()) {
  119. 119. XMPP Sending with Gaelyk def recipient = 'tlberglund@gmail.com' if (xmpp.getPresence(recipient).isAvailable()) { def status = xmpp.send(to: recipient, body: "Glad you're into Gaelyk!") if (!status.isSuccessful()) { // ...
  120. 120. XMPP Sending with Gaelyk def recipient = 'tlberglund@gmail.com' if (xmpp.getPresence(recipient).isAvailable()) { def status = xmpp.send(to: recipient, body: "Glad you're into Gaelyk!") if (!status.isSuccessful()) { // ... } }
  121. 121. XMPP Receiving
  122. 122. XMPP Receiving Enable in appengine-web.xml
  123. 123. XMPP Receiving Enable in appengine-web.xml Enable built-in servlet in web.xml
  124. 124. XMPP Receiving Enable in appengine-web.xml Enable built-in servlet in web.xml /war/WEB-INF/groovy/jabber.groovy
  125. 125. XMPP Receiving Enable in appengine-web.xml Enable built-in servlet in web.xml /war/WEB-INF/groovy/jabber.groovy The “message” intrinsic variable
  126. 126. Plugins
  127. 127. Plugins
  128. 128. Plugins Analogous to Grails plugins
  129. 129. Plugins Analogous to Grails plugins Mini Gaelyk apps
  130. 130. Plugins Analogous to Grails plugins Mini Gaelyk apps plugins/xxxPluginDescriptor.groovy
  131. 131. Plugins Analogous to Grails plugins Mini Gaelyk apps plugins/xxxPluginDescriptor.groovy Bundled as ZIP files
  132. 132. Plugins Analogous to Grails plugins Mini Gaelyk apps plugins/xxxPluginDescriptor.groovy Bundled as ZIP files Ad-hoc discovery and distribution
  133. 133. Development
  134. 134. What about Services in development?
  135. 135. GAE Emulation
  136. 136. GAE Emulation Datastore simulated in filesystem
  137. 137. GAE Emulation Datastore simulated in filesystem General Administration
  138. 138. GAE Emulation Datastore simulated in filesystem General Administration http://localhost:8080/_ah/admin
  139. 139. GAE Emulation Datastore simulated in filesystem General Administration http://localhost:8080/_ah/admin Authentication
  140. 140. GAE Emulation Datastore simulated in filesystem General Administration http://localhost:8080/_ah/admin Authentication http://localhost:8080/_ah/login
  141. 141. GAE Emulation Datastore simulated in filesystem General Administration http://localhost:8080/_ah/admin Authentication http://localhost:8080/_ah/login http://localhost:8080/_ah/logout
  142. 142. Code
  143. 143. On github git@github.com:tlberglund/august-stories.git git@github.com:tlberglund/august-demo.git
  144. 144. Thank You Tim Berglund www.augusttechgroup.com tim.berglund@augusttechgroup.com @tlberglund Using Your Existing Team
  145. 145. Photo Credits Parchment Background http://www.photoshopstar.com/effects/recreate-indiana-jones-text-effect/
  • shashisatya

    Mar. 28, 2011
  • mrjabba

    Jul. 25, 2010
  • limcheekin

    Jul. 9, 2010
  • joeltan

    Jul. 8, 2010
  • glaforge

    Jun. 18, 2010

Gaelyk is a lightweight Groovy web application framework built specifically for the Google App Engine. It provides a fast, easy way to build simply applications in Groovy and host them for free on the GAE.

Vues

Nombre de vues

3 159

Sur Slideshare

0

À partir des intégrations

0

Nombre d'intégrations

293

Actions

Téléchargements

0

Partages

0

Commentaires

0

Mentions J'aime

5

×