SlideShare a Scribd company logo
Google App Engine by example
About me 
 Linked[in]: ua.linkedin.com/in/invaa/ 
 e-mail: alex@zamkovyi.name
Google App Engine 
 PaaS 
 264k websites (258k is active) 
URL: http://trends.builtwith.com/hosting/Google-App- 
Engine 
 Coca-cola, Ubisoft, Rovio, BestBuy, Sony Music, ... 
URL: https://cloud.google.com/customers/
Demo 
 Tic Tac Toe using Google Endpoints 
 Features: 
 API 
 Web frontend 
 Android client 
 Deployed: 
https://cloudendpointstic.appspot.com 
 Sources: 
https://github.com/GoogleCloudPlatform
Plan 
Get to know the Google App Engine (GAE) while making 
a simple jQuery Calendar (aka “Google Calendar killer”) 
and put the app in the Google Cloud.
Google app engine by example
Calendar app 
 Events with persistence in the Google Cloud 
 Start 
 End 
 Title 
 Description 
 Color 
 Attenders 
 Add events 
 Move events
Requirements and Prerequisites 
 JDK 1.7 (recommended) 
 Apache Maven 3.1+ 
 MySQL 5+ (for local dev server) 
 Google account 
 Application ID 
 IDE 
More: 
https://cloud.google.com/appengine/docs/java/gettingstarte 
d/setup
TODO 
 V1: Project creation and structure 
 V2: Spring MVC 
 V3: View with jQuery Calendar 
 V4: Persistence with Cloud SQL 
 V5: Persistence with Cloud Datastore 
 V6: Attenders and colors 
 V7: update events on drop 
 More: https://github.com/invaa/CloudCalendar
Cloud Calendar Service v1 
 Create project structure 
 Run locally
v1. Getting application ID 
 URL: https://appengine.google.com/start
v1. Project creation 
 mvn archetype:generate -Dappengine-version=1.9.13 - 
Dapplication-id=your-app-id - 
Dfilter=com.google.appengine.archetypes: 
 Google Cloud Console
v1. Project structure 
 You'll add your own application 
Java classes to src/main/java/... 
 You'll configure your application 
using the 
file src/main/webapp/WEB-INF/ 
appengine.web.xml 
 You'll configure your application 
deployment using the 
file src/main/webapp/WEB-INF/ 
web.xml
v1. Dependencies. Template 
 appengine-api-1.0-sdk 
 servlet-api 
 Jstl 
 appengine-testing 
 appengine-api-stubs
The Java Development Server 
 jetty-6.1.x (built-in) 
 The development web server simulates the App Engine 
Java runtime environment and all of its services, 
including the datastore 
 More: 
https://cloud.google.com/appengine/docs/java/tools/ 
devserver
Admin console 
 http://localhost:port/_ah/admin
Cloud Calendar Service v2 
 Spring MVC 
 Calendar controller 
 getPages() and “/” mapping 
 Upload Calendar to GAE
v2. Dependencies. Spring MVC 
 <dependency> 
 <groupId>org.springframework</groupId> 
 <artifactId>spring-webmvc</artifactId> 
 <version>${spring.version}</version> 
 </dependency>
v2. Spring MVC. Controller 
 getPages() and “/”
v2. Uploading App 
 mvn appengine:update 
 More: 
https://cloud.google.com/appengine/docs/java/tools/ 
uploadinganapp
Dev Console 
 https://console.developers.google.com/
Google app engine by example
Google app engine by example
Appcfg 
 appengine-java-sdkbinappcfg.cmd [options] 
<action> <war-location> 
 More: 
https://cloud.google.com/appengine/docs/java/tools/ 
uploadinganapp?hl=ru#Uploading_the_App
Cloud Calendar Service v3 
 Button 
 jQuery 
 Calendar 
 Upload Calendar to GAE
v3. Spring MVC. View 
 <link rel="stylesheet" 
href="http://fullcalendar.io/js/fullcalendar- 
2.1.1/fullcalendar.min.css"> 
 <link rel="stylesheet" 
href="http://code.jquery.com/ui/1.11.1/themes/smoothness/jquer 
y-ui.css"> 
 <script src="http://code.jquery.com/jquery- 
1.10.2.min.js"></script> 
 <script src="http://code.jquery.com/ui/1.11.1/jquery-ui. 
min.js"></script> 
 <script src="http://fullcalendar.io/js/fullcalendar- 
2.1.1/lib/moment.min.js"></script> 
 <script src="http://fullcalendar.io/js/fullcalendar- 
2.1.1/fullcalendar.min.js"></script>
v3. Spring MVC. View 
body { 
margin: 0; 
padding: 0; 
font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif; 
font-size: 14px; 
} 
#script-warning { 
display: none; 
background: #eee; 
border-bottom: 1px solid #ddd; 
padding: 0 10px; 
line-height: 40px; 
text-align: center; 
font-weight: bold; 
font-size: 12px; 
color: red; 
} 
#calendar, #container { 
max-width: 900px; 
margin: 40px auto; 
padding: 0 10px; 
}
v3. Create event form 
label, input { 
display: block; 
} 
input.text { 
margin-bottom: 12px; 
width: 95%; 
padding: .4em; 
} 
fieldset { 
padding: 0; 
border: 0; 
margin-top: 25px; 
} 
div#users-contain { 
width: 350px; 
margin: 20px 0; 
} 
div#users-contain table { 
margin: 1em 0; 
border-collapse: collapse; 
width: 100%; 
} 
div#users-contain table td, div#users-contain 
table th { 
border: 1px solid #eee; 
padding: .6em 10px; 
text-align: left; 
} 
.ui-dialog .ui-state-error { 
padding: .3em; 
} 
.validateTips { 
border: 1px solid transparent; 
padding: 0.3em; 
}
v3. Create event form 
function updateTips(t) { 
tips 
.text(t) 
.addClass("ui-state-highlight"); 
setTimeout(function () { 
tips.removeClass("ui-state-highlight", 1500); 
}, 500); 
} 
function checkLength(o, n, min, max) { 
if (o.val().length > max || o.val().length < min) { 
o.addClass("ui-state-error"); 
updateTips("Length of " + n + " must be between " + 
min + " and " + max + "."); 
return false; 
} else { 
return true; 
} 
} 
function checkRegexp(o, regexp, n) { 
if (!( regexp.test(o.val()) )) { 
o.addClass("ui-state-error"); 
updateTips(n); 
return false; 
} else { 
return true; 
} 
} 
function addEvent() { 
// 
} 
//dialog code 
form = 
dialog.find("form").on("submit", 
function (event) { 
event.preventDefault(); 
}); 
$("#create-event"). 
button().on("click", function () { 
dialog.dialog("open"); 
});
Add some persistency 
I am CRUD!
Datastore and RDBMS
Cloud Calendar Service v4 
 Model 
 Persistence
v4. Cloud SQL 
 Spring Data 
 EclipseLink JPA Provider
v4. Cloud SQL. Dependencies 
<dependency> 
<groupId>mysql</groupId> 
<artifactId>mysql-connector-java</ 
artifactId> 
<version>5.1.25</version> 
</dependency> 
<dependency> 
<groupId>org.eclipse.persistence</groupId> 
<artifactId>org.eclipse.persistence.jpa</artifactId 
> 
<version>2.4.2</version> 
</dependency> 
<dependency> 
<groupId>org.springframework.data</groupId> 
<artifactId>spring-data-jpa</artifactId> 
<version>${spring.data.version}</version> 
</dependency> 
<dependency> 
<groupId>com.fasterxml.jackson.core< 
/groupId> 
<artifactId>jackson-databind</ 
artifactId> 
<version>2.3.2</version> 
</dependency>
v4. Cloud SQL. Context 
<persistence-unit name="jpa.unit"> 
<provider>org.eclipse.persistence.jpa.PersistenceProvider</ 
provider> 
<class>com.calendar.service.model.Event</class> 
<exclude-unlisted-classes>true</exclude-unlisted-classes> 
<properties> 
<property name="eclipselink.jdbc.url" 
value="jdbc:mysql://127.0.0.1:3306/demo"/> 
<property name="eclipselink.jdbc.driver" 
value="com.mysql.jdbc.Driver"/> 
<!-- Production --> 
<!--<property name="eclipselink.jdbc.driver" 
value="com.mysql.jdbc.GoogleDriver" />--> 
<!--<property name="eclipselink.jdbc.url" 
value="jdbc:google:mysql://your-instance-name/ 
demo?user=root" />--> 
<property name="eclipselink.jdbc.user" 
value="root"/> 
<property name="eclipselink.jdbc.password" 
value=""/> 
</properties> 
</persistence-unit> 
<bean id="entityManagerFactory" 
class="org.springframework.orm.jpa.LocalContainerEntityMa 
nagerFactoryBean"> 
<property name="persistenceUnitName" value="jpa.unit" 
/> 
<property name="jpaVendorAdapter"> 
<bean 
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVe 
ndorAdapter"> 
<property name="showSql" value="true"/> 
<property name="generateDdl" value="true"/> 
<property name="databasePlatform" 
value="org.eclipse.persistence.platform.database.MySQLPlatf 
orm"/> 
</bean> 
</property> 
<property name="jpaPropertyMap"> 
<props> 
<prop key="eclipselink.weaving">false</prop> 
</props> 
</property> 
</bean>
v4. Cloud SQL. Other 
 @Temporal(TemporalType.TIMESTAMP) 
 <use-google-connector-j>true</use-google-connector- 
j>
v4. Spring MVC. Model 
 Event 
 Repository
v4. Cloud SQL. Deployment 
 Create DB (dev vs production) 
 More: 
https://code.google.com/apis/console/b/0/?noredirect 
&pli=1#project:920231937966:sql
Cloud Calendar Service v5 
 Persistence with Google Datastore 
 Upload Calendar to GAE
v5. Cloud Datastore 
 DataNucleus 
 DataNucleus App Engine Plugin 
 Spring Data 
 More: 
https://cloud.google.com/appengine/docs/java/datast 
ore/jpa/overview
v5. Dependencies. Cloud Datastore 
<dependency> 
<groupId>org.datanucleus</groupId> 
<artifactId>javax.persistence</artifactId> 
<version>2.1.0</version> 
</dependency> 
<dependency> 
<groupId>com.google.appengine.orm</groupId> 
<artifactId>datanucleus-appengine</ 
artifactId> 
<version>${datanucleus-appengine. 
version}</version> 
</dependency> 
<dependency> 
<groupId>org.apache.geronimo.specs</groupId> 
<artifactId>geronimo-jpa_ 
2.0_spec</artifactId> 
<version>1.1</version> 
<scope>provided</scope> 
</dependency> 
<dependency> 
<groupId>org.datanucleus</groupId> 
<artifactId>datanucleus-core</ 
artifactId> 
<version>${datanucleus.version}</version> 
</dependency> 
<dependency> 
<groupId>org.datanucleus</groupId> 
<artifactId>datanucleus-api-jpa</ 
artifactId> 
<version>${datanucleus.version}</version> 
</dependency>
v5. Plugins. Enhance entities 
<plugin> 
<groupId>org.datanucleus</groupId> 
<artifactId>datanucleus-maven-plugin</artifactId> 
<version>4.0.0-release</version> 
<configuration> 
<api>JPA</api> 
<persistenceUnitName>jpa.unit</persistenceUnitName> 
<log4jConfiguration>${basedir}/log4j.properties</log4jConfiguration> 
<verbose>true</verbose> 
</configuration> 
<dependencies> 
<dependency> 
<groupId>org.datanucleus</groupId> 
<artifactId>datanucleus-core</artifactId> 
<version>3.1.1</version> 
</dependency> 
</dependencies> 
<executions> 
<execution> 
<phase>process-classes</phase> 
<goals> 
<goal>enhance</goal> 
</goals> 
</execution> 
</executions> 
</plugin>
v4. Cloud SQL. Context 
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provid 
er> 
<properties> 
<property name="datanucleus.ConnectionURL" 
value="appengine" /> 
<property 
name="datanucleus.appengine.datastoreEnableXGTransactions" 
value="true"/> 
<property 
name="datanucleus.appengine.ignorableMetaDataBehavior" 
value="NONE" /> 
</properties>
v5. Spring-data and Cloud Datastore 
 Repository
Cloud Calendar Service v6 
 Attenders and colors 
 Upload Calendar to GAE
v6. Attenders and colors 
 Colored events 
 Attenders entity 
 OneToMany relation
v6. Color picker 
 <div id="red"></div> 
 <div id="green"></div> 
 <div id="blue"></div> 
 <div id="swatch" class="ui-widget-content ui-corner-all"></ 
div>
v6. Color picker 
#red, #green, #blue { 
float: left; 
clear: left; 
width: 300px; 
margin: 15px; 
} 
#swatch { 
width: 120px; 
height: 100px; 
margin-top: 18px; 
margin-left: 350px; 
background-image: none; 
} 
#red .ui-slider-range { background: #ef2929; } 
#red .ui-slider-handle { border-color: #ef2929; } 
#green .ui-slider-range { background: #8ae234; } 
#green .ui-slider-handle { border-color: #8ae234; } 
#blue .ui-slider-range { background: #729fcf; } 
#blue .ui-slider-handle { border-color: #729fcf; }
v6. Color picker 
function hexFromRGB(r, g, b) { 
var hex = [ 
r.toString( 16 ), 
g.toString( 16 ), 
b.toString( 16 ) 
]; 
$.each( hex, function( nr, val ) { 
if ( val.length === 1 ) { 
hex[ nr ] = "0" + val; 
} 
}); 
return hex.join( "" ).toUpperCase(); 
} 
function refreshSwatch() { 
var red = $( "#red" ).slider( "value" ), 
green = $( "#green" ).slider( "value" ), 
blue = $( "#blue" ).slider( "value" ), 
hex = hexFromRGB( red, green, blue ); 
$( "#swatch" ).css( "background-color", "#" + hex ); 
} 
$(function() { 
$( "#red, #green, #blue" 
).slider({ 
orientation: "horizontal", 
range: "min", 
max: 255, 
value: 127, 
slide: refreshSwatch, 
change: refreshSwatch 
}); 
$( "#red" ).slider( "value", 255 ); 
$( "#green" ).slider( "value", 140 
); 
$( "#blue" ).slider( "value", 60 ); 
});
Cloud Calendar Service v7 
 Update on drop 
 Upload Calendar to GAE
v7. Update on drop 
 eventDrop: function (event, delta, revertFunc) { 
 //update in db 
 $.getJSON("${pageContext.request.contextPath}/updateEventOnDrop", 
 { 
 id: event.id, 
 start: event.start.format() 
 }, 
 function (data) { 
 }) 
 .done(function () { 
 }) 
 .fail(function () { 
 }) 
 .complete(function () { 
 }); 
 }
An App Engine application cannot 
 write to the filesystem. Applications must use the App 
Engine datastore for storing persistent data. Reading 
from the filesystem is allowed, and all application files 
uploaded with the application are available. 
 respond slowly. A web request to an application must 
be handled within a few seconds. Processes that take a 
very long time to respond are terminated to avoid 
overloading the web server. 
 make other kinds of system calls.
JRE White list 
 https://cloud.google.com/appengine/docs/java/jrewhi 
telist
web.xml Features Not Supported 
 App Engine supports the <load-on-startup> element for servlet 
declarations. However, the load actually occurs during the first 
request handled by the web server instance, not prior to it. 
 Some deployment descriptor elements can take a human 
readable display name, description and icon for use in IDEs. App 
Engine doesn't use these, and ignores them. 
 App Engine doesn't support JNDI environment variables (<env-entry>). 
 App Engine doesn't support EJB resources (<resource-ref>). 
 Notification of the destruction of servlets, servlet context, or 
filters is not supported. 
 The <distributable> element is ignored. 
 Servlet scheduling with <run-at> is not supported.
Further reading 
 https://cloud.google.com/appengine/ 
 https://github.com/tommysiu/spring-data-gae/ 
blob/v0.1/README.md 
 https://cloud.google.com/developers/articles/balancing-strong-and- 
eventual-consistency-with-google-cloud-datastore/ 
 http://www.datanucleus.org/products/datanucleus/jpa/maven.h 
tml 
 https://code.google.com/p/datanucleus-appengine/ 
wiki/Compatibility 
 http://www.loop81.com/2013/02/gae-google-app-engine-jpa2- 
maven-and.html 
 http://gae-java-persistence.blogspot.com/ 
 http://www.datanucleus.org/products/datanucleus/jpa/enhance 
r.html
Q&A 
 Thank you! 

More Related Content

PPTX
Deploying applications to Cloud with Google App Engine
PPTX
Meteor Meet-up San Diego December 2014
PDF
In The Trenches With Tomster, Upgrading Ember.js & Ember Data
PPTX
How to customize Spring Boot?
PDF
Vaadin & Web Components
PDF
Vaadin 7.2
PPTX
06. Android Basic Widget and Container
PDF
Spring as a Cloud Platform (Developer Summit 2011 17-C-5)
Deploying applications to Cloud with Google App Engine
Meteor Meet-up San Diego December 2014
In The Trenches With Tomster, Upgrading Ember.js & Ember Data
How to customize Spring Boot?
Vaadin & Web Components
Vaadin 7.2
06. Android Basic Widget and Container
Spring as a Cloud Platform (Developer Summit 2011 17-C-5)

What's hot (20)

PDF
Andy Bosch - JavaServer Faces in the cloud
KEY
Eclipse IAM, Maven Integration For Eclipse
PPT
Maven, Eclipse And OSGi Working Together
PPTX
Progressive Web Apps 101
PDF
Vue, vue router, vuex
PDF
Gradle 2.2, 2.3 news #jggug
PDF
Vue js and Vue Material
PPT
Q4E and Eclipse IAM, Maven integration for Eclipse
PDF
Java Web Programming on Google Cloud Platform [1/3] : Google App Engine
PDF
How to create a skeleton of a Java console application
PDF
*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...
PDF
The Point of Vue - Intro to Vue.js
PDF
Hastening React SSR - Web Performance San Diego
PDF
webcomponents (Jfokus 2015)
PDF
Vaadin Introduction, 7.3 edition
PPT
Apache maven
PDF
Room with a Vue - Introduction to Vue.js
PPS
11 asp.net session16
PDF
Cloud Computing: Changing the software business
PDF
Love at first Vue
Andy Bosch - JavaServer Faces in the cloud
Eclipse IAM, Maven Integration For Eclipse
Maven, Eclipse And OSGi Working Together
Progressive Web Apps 101
Vue, vue router, vuex
Gradle 2.2, 2.3 news #jggug
Vue js and Vue Material
Q4E and Eclipse IAM, Maven integration for Eclipse
Java Web Programming on Google Cloud Platform [1/3] : Google App Engine
How to create a skeleton of a Java console application
*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...
The Point of Vue - Intro to Vue.js
Hastening React SSR - Web Performance San Diego
webcomponents (Jfokus 2015)
Vaadin Introduction, 7.3 edition
Apache maven
Room with a Vue - Introduction to Vue.js
11 asp.net session16
Cloud Computing: Changing the software business
Love at first Vue
Ad

Similar to Google app engine by example (20)

PDF
Code in the Cloud 1st Edition Mark C. Chu-Carroll
PDF
Code in the Cloud 1st Edition Mark C. Chu-Carroll
PDF
Code in the Cloud 1st Edition Mark C. Chu-Carroll
PPTX
Google Cloud Platform
PDF
Download ebooks file Code in the Cloud 1st Edition Mark C. Chu-Carroll all ch...
PDF
Code In The Cloud 1st Edition Mark C Chucarroll
PDF
Cannibalising The Google App Engine
PDF
Google App Engine for Java v0.0.2
PDF
Google Developer Days Brazil 2009 - Java Appengine
PPTX
Google appenginejava.ppt
PDF
CloudConf2011 Introduction to Google App Engine
PPTX
CloudPlatforms-Cloud PLatforms evaluation
KEY
Appengine Nljug
PDF
App Engine Meetup
PDF
Introduction to Google's Cloud Technologies
PDF
2011 july-gtug-high-replication-datastore
PDF
Appscale at CLOUDCOMP '09
KEY
Google App Engine with Gaelyk
PDF
Google App Engine
PDF
Google App Engine Update 2012
Code in the Cloud 1st Edition Mark C. Chu-Carroll
Code in the Cloud 1st Edition Mark C. Chu-Carroll
Code in the Cloud 1st Edition Mark C. Chu-Carroll
Google Cloud Platform
Download ebooks file Code in the Cloud 1st Edition Mark C. Chu-Carroll all ch...
Code In The Cloud 1st Edition Mark C Chucarroll
Cannibalising The Google App Engine
Google App Engine for Java v0.0.2
Google Developer Days Brazil 2009 - Java Appengine
Google appenginejava.ppt
CloudConf2011 Introduction to Google App Engine
CloudPlatforms-Cloud PLatforms evaluation
Appengine Nljug
App Engine Meetup
Introduction to Google's Cloud Technologies
2011 july-gtug-high-replication-datastore
Appscale at CLOUDCOMP '09
Google App Engine with Gaelyk
Google App Engine
Google App Engine Update 2012
Ad

Recently uploaded (20)

PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
medical staffing services at VALiNTRY
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
Materi_Pemrograman_Komputer-Looping.pptx
PDF
Complete React Javascript Course Syllabus.pdf
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Essential Infomation Tech presentation.pptx
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPT
Introduction Database Management System for Course Database
PDF
top salesforce developer skills in 2025.pdf
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
2025 Textile ERP Trends: SAP, Odoo & Oracle
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PTS Company Brochure 2025 (1).pdf.......
Understanding Forklifts - TECH EHS Solution
Softaken Excel to vCard Converter Software.pdf
medical staffing services at VALiNTRY
Wondershare Filmora 15 Crack With Activation Key [2025
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Design an Analysis of Algorithms II-SECS-1021-03
Materi_Pemrograman_Komputer-Looping.pptx
Complete React Javascript Course Syllabus.pdf
Design an Analysis of Algorithms I-SECS-1021-03
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Essential Infomation Tech presentation.pptx
Upgrade and Innovation Strategies for SAP ERP Customers
Introduction Database Management System for Course Database
top salesforce developer skills in 2025.pdf

Google app engine by example

  • 1. Google App Engine by example
  • 2. About me  Linked[in]: ua.linkedin.com/in/invaa/  e-mail: alex@zamkovyi.name
  • 3. Google App Engine  PaaS  264k websites (258k is active) URL: http://trends.builtwith.com/hosting/Google-App- Engine  Coca-cola, Ubisoft, Rovio, BestBuy, Sony Music, ... URL: https://cloud.google.com/customers/
  • 4. Demo  Tic Tac Toe using Google Endpoints  Features:  API  Web frontend  Android client  Deployed: https://cloudendpointstic.appspot.com  Sources: https://github.com/GoogleCloudPlatform
  • 5. Plan Get to know the Google App Engine (GAE) while making a simple jQuery Calendar (aka “Google Calendar killer”) and put the app in the Google Cloud.
  • 7. Calendar app  Events with persistence in the Google Cloud  Start  End  Title  Description  Color  Attenders  Add events  Move events
  • 8. Requirements and Prerequisites  JDK 1.7 (recommended)  Apache Maven 3.1+  MySQL 5+ (for local dev server)  Google account  Application ID  IDE More: https://cloud.google.com/appengine/docs/java/gettingstarte d/setup
  • 9. TODO  V1: Project creation and structure  V2: Spring MVC  V3: View with jQuery Calendar  V4: Persistence with Cloud SQL  V5: Persistence with Cloud Datastore  V6: Attenders and colors  V7: update events on drop  More: https://github.com/invaa/CloudCalendar
  • 10. Cloud Calendar Service v1  Create project structure  Run locally
  • 11. v1. Getting application ID  URL: https://appengine.google.com/start
  • 12. v1. Project creation  mvn archetype:generate -Dappengine-version=1.9.13 - Dapplication-id=your-app-id - Dfilter=com.google.appengine.archetypes:  Google Cloud Console
  • 13. v1. Project structure  You'll add your own application Java classes to src/main/java/...  You'll configure your application using the file src/main/webapp/WEB-INF/ appengine.web.xml  You'll configure your application deployment using the file src/main/webapp/WEB-INF/ web.xml
  • 14. v1. Dependencies. Template  appengine-api-1.0-sdk  servlet-api  Jstl  appengine-testing  appengine-api-stubs
  • 15. The Java Development Server  jetty-6.1.x (built-in)  The development web server simulates the App Engine Java runtime environment and all of its services, including the datastore  More: https://cloud.google.com/appengine/docs/java/tools/ devserver
  • 16. Admin console  http://localhost:port/_ah/admin
  • 17. Cloud Calendar Service v2  Spring MVC  Calendar controller  getPages() and “/” mapping  Upload Calendar to GAE
  • 18. v2. Dependencies. Spring MVC  <dependency>  <groupId>org.springframework</groupId>  <artifactId>spring-webmvc</artifactId>  <version>${spring.version}</version>  </dependency>
  • 19. v2. Spring MVC. Controller  getPages() and “/”
  • 20. v2. Uploading App  mvn appengine:update  More: https://cloud.google.com/appengine/docs/java/tools/ uploadinganapp
  • 21. Dev Console  https://console.developers.google.com/
  • 24. Appcfg  appengine-java-sdkbinappcfg.cmd [options] <action> <war-location>  More: https://cloud.google.com/appengine/docs/java/tools/ uploadinganapp?hl=ru#Uploading_the_App
  • 25. Cloud Calendar Service v3  Button  jQuery  Calendar  Upload Calendar to GAE
  • 26. v3. Spring MVC. View  <link rel="stylesheet" href="http://fullcalendar.io/js/fullcalendar- 2.1.1/fullcalendar.min.css">  <link rel="stylesheet" href="http://code.jquery.com/ui/1.11.1/themes/smoothness/jquer y-ui.css">  <script src="http://code.jquery.com/jquery- 1.10.2.min.js"></script>  <script src="http://code.jquery.com/ui/1.11.1/jquery-ui. min.js"></script>  <script src="http://fullcalendar.io/js/fullcalendar- 2.1.1/lib/moment.min.js"></script>  <script src="http://fullcalendar.io/js/fullcalendar- 2.1.1/fullcalendar.min.js"></script>
  • 27. v3. Spring MVC. View body { margin: 0; padding: 0; font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif; font-size: 14px; } #script-warning { display: none; background: #eee; border-bottom: 1px solid #ddd; padding: 0 10px; line-height: 40px; text-align: center; font-weight: bold; font-size: 12px; color: red; } #calendar, #container { max-width: 900px; margin: 40px auto; padding: 0 10px; }
  • 28. v3. Create event form label, input { display: block; } input.text { margin-bottom: 12px; width: 95%; padding: .4em; } fieldset { padding: 0; border: 0; margin-top: 25px; } div#users-contain { width: 350px; margin: 20px 0; } div#users-contain table { margin: 1em 0; border-collapse: collapse; width: 100%; } div#users-contain table td, div#users-contain table th { border: 1px solid #eee; padding: .6em 10px; text-align: left; } .ui-dialog .ui-state-error { padding: .3em; } .validateTips { border: 1px solid transparent; padding: 0.3em; }
  • 29. v3. Create event form function updateTips(t) { tips .text(t) .addClass("ui-state-highlight"); setTimeout(function () { tips.removeClass("ui-state-highlight", 1500); }, 500); } function checkLength(o, n, min, max) { if (o.val().length > max || o.val().length < min) { o.addClass("ui-state-error"); updateTips("Length of " + n + " must be between " + min + " and " + max + "."); return false; } else { return true; } } function checkRegexp(o, regexp, n) { if (!( regexp.test(o.val()) )) { o.addClass("ui-state-error"); updateTips(n); return false; } else { return true; } } function addEvent() { // } //dialog code form = dialog.find("form").on("submit", function (event) { event.preventDefault(); }); $("#create-event"). button().on("click", function () { dialog.dialog("open"); });
  • 30. Add some persistency I am CRUD!
  • 32. Cloud Calendar Service v4  Model  Persistence
  • 33. v4. Cloud SQL  Spring Data  EclipseLink JPA Provider
  • 34. v4. Cloud SQL. Dependencies <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</ artifactId> <version>5.1.25</version> </dependency> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa</artifactId > <version>2.4.2</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${spring.data.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core< /groupId> <artifactId>jackson-databind</ artifactId> <version>2.3.2</version> </dependency>
  • 35. v4. Cloud SQL. Context <persistence-unit name="jpa.unit"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</ provider> <class>com.calendar.service.model.Event</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="eclipselink.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/demo"/> <property name="eclipselink.jdbc.driver" value="com.mysql.jdbc.Driver"/> <!-- Production --> <!--<property name="eclipselink.jdbc.driver" value="com.mysql.jdbc.GoogleDriver" />--> <!--<property name="eclipselink.jdbc.url" value="jdbc:google:mysql://your-instance-name/ demo?user=root" />--> <property name="eclipselink.jdbc.user" value="root"/> <property name="eclipselink.jdbc.password" value=""/> </properties> </persistence-unit> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityMa nagerFactoryBean"> <property name="persistenceUnitName" value="jpa.unit" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVe ndorAdapter"> <property name="showSql" value="true"/> <property name="generateDdl" value="true"/> <property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatf orm"/> </bean> </property> <property name="jpaPropertyMap"> <props> <prop key="eclipselink.weaving">false</prop> </props> </property> </bean>
  • 36. v4. Cloud SQL. Other  @Temporal(TemporalType.TIMESTAMP)  <use-google-connector-j>true</use-google-connector- j>
  • 37. v4. Spring MVC. Model  Event  Repository
  • 38. v4. Cloud SQL. Deployment  Create DB (dev vs production)  More: https://code.google.com/apis/console/b/0/?noredirect &pli=1#project:920231937966:sql
  • 39. Cloud Calendar Service v5  Persistence with Google Datastore  Upload Calendar to GAE
  • 40. v5. Cloud Datastore  DataNucleus  DataNucleus App Engine Plugin  Spring Data  More: https://cloud.google.com/appengine/docs/java/datast ore/jpa/overview
  • 41. v5. Dependencies. Cloud Datastore <dependency> <groupId>org.datanucleus</groupId> <artifactId>javax.persistence</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>com.google.appengine.orm</groupId> <artifactId>datanucleus-appengine</ artifactId> <version>${datanucleus-appengine. version}</version> </dependency> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-jpa_ 2.0_spec</artifactId> <version>1.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-core</ artifactId> <version>${datanucleus.version}</version> </dependency> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-api-jpa</ artifactId> <version>${datanucleus.version}</version> </dependency>
  • 42. v5. Plugins. Enhance entities <plugin> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-maven-plugin</artifactId> <version>4.0.0-release</version> <configuration> <api>JPA</api> <persistenceUnitName>jpa.unit</persistenceUnitName> <log4jConfiguration>${basedir}/log4j.properties</log4jConfiguration> <verbose>true</verbose> </configuration> <dependencies> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-core</artifactId> <version>3.1.1</version> </dependency> </dependencies> <executions> <execution> <phase>process-classes</phase> <goals> <goal>enhance</goal> </goals> </execution> </executions> </plugin>
  • 43. v4. Cloud SQL. Context <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provid er> <properties> <property name="datanucleus.ConnectionURL" value="appengine" /> <property name="datanucleus.appengine.datastoreEnableXGTransactions" value="true"/> <property name="datanucleus.appengine.ignorableMetaDataBehavior" value="NONE" /> </properties>
  • 44. v5. Spring-data and Cloud Datastore  Repository
  • 45. Cloud Calendar Service v6  Attenders and colors  Upload Calendar to GAE
  • 46. v6. Attenders and colors  Colored events  Attenders entity  OneToMany relation
  • 47. v6. Color picker  <div id="red"></div>  <div id="green"></div>  <div id="blue"></div>  <div id="swatch" class="ui-widget-content ui-corner-all"></ div>
  • 48. v6. Color picker #red, #green, #blue { float: left; clear: left; width: 300px; margin: 15px; } #swatch { width: 120px; height: 100px; margin-top: 18px; margin-left: 350px; background-image: none; } #red .ui-slider-range { background: #ef2929; } #red .ui-slider-handle { border-color: #ef2929; } #green .ui-slider-range { background: #8ae234; } #green .ui-slider-handle { border-color: #8ae234; } #blue .ui-slider-range { background: #729fcf; } #blue .ui-slider-handle { border-color: #729fcf; }
  • 49. v6. Color picker function hexFromRGB(r, g, b) { var hex = [ r.toString( 16 ), g.toString( 16 ), b.toString( 16 ) ]; $.each( hex, function( nr, val ) { if ( val.length === 1 ) { hex[ nr ] = "0" + val; } }); return hex.join( "" ).toUpperCase(); } function refreshSwatch() { var red = $( "#red" ).slider( "value" ), green = $( "#green" ).slider( "value" ), blue = $( "#blue" ).slider( "value" ), hex = hexFromRGB( red, green, blue ); $( "#swatch" ).css( "background-color", "#" + hex ); } $(function() { $( "#red, #green, #blue" ).slider({ orientation: "horizontal", range: "min", max: 255, value: 127, slide: refreshSwatch, change: refreshSwatch }); $( "#red" ).slider( "value", 255 ); $( "#green" ).slider( "value", 140 ); $( "#blue" ).slider( "value", 60 ); });
  • 50. Cloud Calendar Service v7  Update on drop  Upload Calendar to GAE
  • 51. v7. Update on drop  eventDrop: function (event, delta, revertFunc) {  //update in db  $.getJSON("${pageContext.request.contextPath}/updateEventOnDrop",  {  id: event.id,  start: event.start.format()  },  function (data) {  })  .done(function () {  })  .fail(function () {  })  .complete(function () {  });  }
  • 52. An App Engine application cannot  write to the filesystem. Applications must use the App Engine datastore for storing persistent data. Reading from the filesystem is allowed, and all application files uploaded with the application are available.  respond slowly. A web request to an application must be handled within a few seconds. Processes that take a very long time to respond are terminated to avoid overloading the web server.  make other kinds of system calls.
  • 53. JRE White list  https://cloud.google.com/appengine/docs/java/jrewhi telist
  • 54. web.xml Features Not Supported  App Engine supports the <load-on-startup> element for servlet declarations. However, the load actually occurs during the first request handled by the web server instance, not prior to it.  Some deployment descriptor elements can take a human readable display name, description and icon for use in IDEs. App Engine doesn't use these, and ignores them.  App Engine doesn't support JNDI environment variables (<env-entry>).  App Engine doesn't support EJB resources (<resource-ref>).  Notification of the destruction of servlets, servlet context, or filters is not supported.  The <distributable> element is ignored.  Servlet scheduling with <run-at> is not supported.
  • 55. Further reading  https://cloud.google.com/appengine/  https://github.com/tommysiu/spring-data-gae/ blob/v0.1/README.md  https://cloud.google.com/developers/articles/balancing-strong-and- eventual-consistency-with-google-cloud-datastore/  http://www.datanucleus.org/products/datanucleus/jpa/maven.h tml  https://code.google.com/p/datanucleus-appengine/ wiki/Compatibility  http://www.loop81.com/2013/02/gae-google-app-engine-jpa2- maven-and.html  http://gae-java-persistence.blogspot.com/  http://www.datanucleus.org/products/datanucleus/jpa/enhance r.html
  • 56. Q&A  Thank you! 