淺談 Groovy 與 AWS 雲端應用開發整合

7,226 views
7,526 views

Published on

使用 Groovy 相關工具及技術,讓現代 Java 軟體開發更省時省力,是 Java 程式設計師提升工作效率的捷徑。本次議程分享的內容包括:
(1)撰寫 Groovy Script 的妙用;
(2)自動化的 Gradle 專案建置;
(3)認識 Grails 敏捷網站開發框架;
(4)利用 Geb 進行網頁自動化測試;
(5)部署 Amazon Web Services 雲端應用

於 Oracle 主辦的 2014 Java Developer Day 發表。
http://www.codedata.com.tw/event/javaday/2014/agenda.html

0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,226
On SlideShare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
Downloads
84
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide

淺談 Groovy 與 AWS 雲端應用開發整合

  1. 1. Groovy & AWS! 雲端應⽤用開發整合 林彥宏! 思創軟體 Senior Software Developer! lyhcode.info / lyhcode@gmail.com
  2. 2. 3 Polyglot Programming for Java developers Scala Clojure JRuby Jython Rhino Groovy
  3. 3. 4 A language that doesn't affect the way you think about programming, is not worth knowing. — Alan Perlis “
  4. 4. 5 Hello, Groovy. very good and enjoyable fashionable, modern, and fun
  5. 5. 6 2003 1.0 2007 designed by James Strachan project manager Guillaume LaForge glaforge.appspot.com 2.0 2012 https://github.com/groovy/groovy-core Apache License, Version 2.0 3.0 ? JSR-241 Groovy – A New Standard Programming Language for the Java Platform 2004 2.3.5 2.4.0-beta Groovy History J2SE 5.0 Java SE 6 Java SE 7 1.8 20112006 JAX 2007 Innovation Awards 2008 2009 1995 Spring, VMware
  6. 6. 7 JSR-223 Scripting for the Java Platform JSR-241 The Groovy Programming Language
  7. 7. Groovy for Java Developers • Scripting language • Almost-zero learning curve • More productive • Get things done faster, better, and more easily 8
  8. 8. 9 本投影⽚片所包含的商標與⽂文字皆屬原著作者所有
  9. 9. 10 Java Groovy Groovy Second language to learn after Java. Gradle A better way to build your Java (EE) projects. Geb The best way to test your web applications automatically. Language Development Tools Framework Grails Rapid web development framework based on Groovy and Java.
  10. 10. INSTALL GROOVY 11
  11. 11. GVM • Groovy enVironment Manager ! • Like RVM for Ruby or NVM for Node.js 12
  12. 12. Install GVM 13 # install gvm curl -s get.gvmtool.net | bash Platform supported: • Linux • Mac OSX • Windows (with Cygwin) • Solaris • FreeBSD
  13. 13. Using GVM 14 gvm install groovy 2.3.4 gvm install grails 2.4.2 gvm install gradle 2.0 candidate version
  14. 14. 15 gvm ls groovy gvm use groovy 2.3.4
  15. 15. GETTING STARTED 16
  16. 16. 17 groovy the interpreter groovyc the compiler groovysh Groovy Shell, REPL (Read-eval-print loop) groovyConsole GUI editor for groovy Compiling Groovy code to Java bytecode
  17. 17. 18 Groovy Console
  18. 18. 19 Groovy Web Console groovyconsole.appspot.com
  19. 19. 20 Code Editor v.s. IDE 1. Groovy / Grails Tool Suite
 (Eclipse-based) 2. NetBeans 6.5+ 3. IntelliJ IDEA 1. Vim 2. Sublime Text 3. Gedit
  20. 20. Hello World in Java 21 1. public class HelloWorld { 2. public static void main(String[] args) { 3. System.out.println("Hello! World!"); 4. } 5. } 6.
  21. 21. From Java To Groovy 22 1. public class HelloWorld { 2. public static void main(String[] args) { 3. System.out.println("Hello! World!"); 4. } 5. } 6.
  22. 22. Hello World in Groovy 23 1. println "Hello! World!" 2.
  23. 23. Create Object 24 1. class Person { 2. def name 3. def age 4. } 5. 6. def john = new Person(name: 'John', age: 35) 7. println john.name 8. dynamic typing
  24. 24. GString 25 1. println "Name: ${john.name}, Age: ${john.age}" 2. 3. println "Birth year: ${2014 - john.age}" 4.
  25. 25. Regex (regular expression) 26 1. pattern = /[0-9]{4}-[0-9]{2}-[0-9]{2}/ 2. 3. assert "2014-08-01" ==~ pattern 4. 5. // Assertion failed 6. assert "103-08-01" ==~ pattern 7.
  26. 26. Closure 27 1. def add = { x, y -> 2. x + y 3. } 4. 5. def z 6. 7. z = add 1, 2 8.
  27. 27. GDK (Groovy JDK) 28 1. new File('input.txt').text 2. 3. new URL('http://java.com/').text 4.
  28. 28. GDK (Groovy JDK) 29 1. new File('/tmp').eachFileMatch(~/.*.sock/) { 2. file -> 3. println file.absolutePath 4. } 5.
  29. 29. Metaprogramming 30 1. String.metaClass.hello = { 2. "Hello ${delegate}" 3. } 4. 5. // Say Hello to John 6. "John".hello() 7.
  30. 30. Metaprogramming 31 1. String.metaClass.escapeHtml = { 2. delegate 3. .replaceAll('<', '&lt;') 4. .replaceAll('>', '&gt;') 5. .replaceAll(' ', '&nbsp;') 6. } 7. 8. "<p>line1<br />line2</p>".escapeHtml() 9.
  31. 31. List 32 1. def books = ["Java Cookbook", "Java in a Nutshell"] 2. 3. assert books instanceof ArrayList //;true 4. 5. println books.size() 6. println books[0] 7. 8. books << "Functional Programming in Java" 9. 10. books.each { println it } 11.
  32. 32. Map 33 1. def votes = [java: 9, groovy: 12, scala: 7] 2. 3. assert votes instanceof HashMap //;true 4. 5. votes.jruby = 5 6. votes << [clojure: 11] 7. 8. println votes.size() 9. println votes.java 10. 11. votes.each { println "${it.key} = ${it.value}" } 12.
  33. 33. 34 1. ArrayList list = [1, 2, 3] + [4, 5, 6] 2. 3. list += [7, 8] 4. list << 9 5. 6. 7. HashMap map = [a: 1, b: 2, c: 3] + [d: 4, e: 5] 8. 9. map += [f: 6, g: 7] 10. map << [h: 8] 11.
  34. 34. JSON Support • Groovy 1.8 introduces a build-in JSON builder and parser ! groovy.json.JsonSlurper groovy.json.JsonBuilder 35
  35. 35. Using JsonSlurper 36 1. import groovy.json.* 2. 3. def result = new JsonSlurper().parseText(''' 4. { 5. "first_name": "John", 6. "last_name": "Smith" 7. } 8. ''') 9. 10. result.first_name 11. result.last_name 12.
  36. 36. sample.json 37 1. { 2. "events": [ 3. { 4. "name": "2014 Java Developer Day", 5. "date": "2014/08/01" 6. }, 7. { 8. "name": "JCConf TW 2014", 9. "date": "2014/11/15" 10. } 11. ] 12. } 13.
  37. 37. Reading JSON 38 1. import groovy.json.* 2. 3. def payload = new File('sample.json') 4. // or new URL(‘http://.../sample.json’) 5. 6. def slurper = new JsonSlurper() 7. def result = slurper.parse(payload, 'UTF-8') 8.
  38. 38. Reading JSON 39 1. result.events.size() 2. //;;=> 2 3. 4. result.events.first().name 5. //;;=> 2014 Java Developer Day 6. 7. // List all events 8. result.events.each { 9. println it.name 10. } 11.
  39. 39. Building JSON 40 1. def builder = new groovy.json.JsonBuilder() 2. def root = builder.people { 3. person { 4. firstName 'John' 5. lastName 'Smith' 6. } 7. } 8. 9. builder.toPrettyString() 10. { "people": { "person": { "firstName": "John", "lastName": "Smith" } } } program output
  40. 40. 41 Groovy and DSL (Domain-Specific Languages)
  41. 41. Groovy DSL • DSL: Domain-Specific Language • Could be implemented with Groovy Builders 42 sendmail { from me to someone message “leave a message” } (pseudo code)
  42. 42. AntBuilder 43 1. new AntBuilder().zip( 2. destFile: 'file1.zip', 3. basedir: 'dir' 4. ) 5. Using AntBuilder to compress a folder
  43. 43. 44 1. new AntBuilder().mail( 2. mailhost: 'smtp.gmail.com', 3. mailport: 465, ssl: true, 4. user: 'username', password: 'password', 5. messagemimetype: 'text/html', 6. subject: 'Test Sending E-Mail with AntBuilder') 7. { 8. from name: 'AntBuilder', address: 'john@company' 9. to address: 'jack@company' 10. cc address: 'jackson@company' 11. message "<p><b>Test</b> only.</p>" 12. } Using AntBuilder to send a email
  44. 44. GRADLE Development Tools 45
  45. 45. Gradle • Build automation for Java/Java EE/Groovy projects. • Based on Groovy. 46
  46. 46. 47 Apache Ant XML (build.xml) Apache Maven XML (pom.xml) Gradle Groovy DSL (build.gradle)
  47. 47. Define a Gradle Task 48 1. task hello { 2. doLast { 3. println "Hello" 4. } 5. } 6. build.gradle gradle hello
  48. 48. Default Java Project Layout 49 src/main/ java groovy resources webapp src/test/ java groovy resources build.gradle
  49. 49. Build a Java project 50 1. apply plugin: 'java' 2. 3. repositories { 4. mavenCentral() 5. } 6. 7. dependencies { 8. compile 'commons-codec:commons-codec:1.8' 9. } 10. Use the Maven Central Repository Dependencies Management
  50. 50. Execute a Gradle Task 51 gradle build gradle test gradle war gradle jettyRun gradle javadoc task command
  51. 51. Gradle Plugins 52 1. apply plugin: 'java' 2. apply plugin: 'groovy' 3. apply plugin: 'scala' 4. apply plugin: 'war' 5. apply plugin: 'maven' 6. apply plugin: 'wrapper' 7. apply plugin: 'application' 8. apply plugin: 'jetty' 9. apply plugin: 'java' 10. apply plugin: 'eclipse' 11. apply plugin: 'idea' 12. apply plugin: 'codenarc' 13. apply plugin: 'checkstyle' 14. // and more 15.
  52. 52. Gradle Wrapper 53 ./gradlew build gradlew.bat build For Linux, Mac OS X users… For Windows users…
  53. 53. Gradle Test Report 54
  54. 54. GEB Development Tools 55
  55. 55. Geb • A browser automation solution. • Based on Groovy and Selenium WebDriver. 56
  56. 56. Getting Started 57 1. @Grapes([ 2. @Grab('org.gebish:geb-core:0.9.2'), 3. @Grab('org.seleniumhq.selenium:selenium-firefox-driver:2.42.0'), 4. @Grab('org.seleniumhq.selenium:selenium-support:2.42.0') 5. ]) 6. import geb.Browser ! 8. Browser.drive { 9. go "http://www.google.com.tw/" 10. } 11.
  57. 57. Geb Navigator API 58 1. println $('h3.heading').text() 2. $('input', name: 'fullName').value('user1') 3. $('button#btnSubmit').click() 4. 1. <h3 class=“heading”>…</h3> 2. <form action=“…”> 3. <input name=“fullName” value=“” /> 4. <button id=“btnSubmit” class=“btn-primary”>Submit</button> 5. </form> HTML Geb
  58. 58. Browser Automation 59 1. Browser.drive { 2. go 'https://www.google.com.tw/' 3. 4. $('input', name: 'q').value('CodeData') 5. $('input', name: 'btnI').click() 6. 7. waitFor { title.endsWith('CodeData') } 8. 9. println $('div.article h3 a').text() 10. } 11.
  59. 59. GROOVY SCRIPTING 60
  60. 60. 61 Groovy Scripts Java Library Command- line Tools Run with Shell or Cron jobs
  61. 61. Execute a Groovy Script 62 groovy myscript.groovy arg1 myscript arg1
  62. 62. Execute Groovy as Shell Script 1. #!/usr/bin/env groovy 2. 3. args.each { 4. println "arg: ${it}" 5. } 6. 63 chmod a+x myscript ./myscript arg1 ! file name: myscript
  63. 63. DIVE INTO AWS 64
  64. 64. 65 S3 (Simple Storage Service) Elastic Beanstalk EC2 (Elastic Compute Cloud) RDS (Amazon Relational Database Service) CloudFront (CDN) Using AWS SDK with Groovy Script
  65. 65. Grapes and @Grab() 66 1. @Grab('com.amazonaws:aws-java-sdk:1.8.3') 2. import com.amazonaws.auth.* 3. import com.amazonaws.services.s3.* 4. Grapes will do: 1. Resolving dependencies 2. Download packages (*.jar) from Maven repositories group artifact com.amazonaws:aws-java-sdk:1.8.3 version
  66. 66. 67 aws-java-sdk-1.8.3.jar commons-logging-1.1.1.jar httpclient-4.2.jar httpcore-4.2.jar commons-codec-1.3.jar jackson-core-2.1.1.jar jackson-databind-2.1.1.jar jackson-annotations-2.1.1.jar joda-time-2.3.jar ~/.groovy/grapes depends on All *.jar files will be stored in this folder
  67. 67. s3upload.groovy 68 1. def credentials = new BasicAWSCredentials( 2. accessKey, 3. secretKey 4. ) 5. 6. // Get S3 client 7. def s3client = new AmazonS3Client(credentials) 8.
  68. 68. 69 9. // Create a S3 Bucket 10. s3client.createBucket('s3.myhost') 11. 12. // Upload a file to S3 13. def localFile = new File('path-to-local-file') ! 15. s3client.putObject( 16. 's3.myhost', 17. 'key-for-remote-file', 18. localFile 19. ) 20.
  69. 69. WAR Deployment on AWS 70 Local WAR file MyApp-1.0.war Amazon S3 Bucket Amazon Amazon Elastic BeansTalk ! Application upload Environmentdeploy Create or update an environment
  70. 70. 71 Accessing Elastic Beanstalk services with Groovy Script + Applications
  71. 71. eb_deploy.groovy 72 1. @Grab('com.amazonaws:aws-java-sdk:1.8.3') 2. import com.amazonaws.auth.* 3. import com.amazonaws.services.s3.* 4. import com.amazonaws.services.elasticbeanstalk.* 5. import com.amazonaws.services.elasticbeanstalk.model.* 6. 7. def credentials = new BasicAWSCredentials(accessKey, secretKey) 8. 9. def s3client = new AmazonS3Client(credentials) 10. def ebclient = new AWSElasticBeanstalkClient(credentials) 11.
  72. 72. 73 12. 13. def bucket = ebclient.createStorageLocation().s3Bucket 14. s3client.putObject(bucket, objectKey, warFile) 15. 16. def request = new CreateApplicationVersionRequest() 17. request.applicationName = 'applicationName' 18. request.versionLabel = 'versionLabel' 19. request.description = 'description' 20. request.autoCreateApplication = true 21. request.sourceBundle = new S3Location(bucket, objectKey) 22. elasticBeanstalk.createApplicationVersion(request) 23. 24. request = new UpdateEnvironmentRequest() 25. request.environmentName = 'environmentName' 26. request.versionLabel = 'versionLabel' 27. elasticBeanstalk.updateEnvironment(request) 28. ① Upload .war to S3 ② Create application version ③ Update environment
  73. 73. GRAILS FRAMEWORK 74
  74. 74. 75 Grails Architecture Grails Groovy Java Virtual Machine Spring Hibernate SiteMesh Java EE
  75. 75. Create a Grails Project 76 grails create-app example cd example
  76. 76. Run 77 grails run-app grails -Dserver.port=8000 run-app Specifies the HTTP port:
  77. 77. 78 Browse http://localhost:8080/example
  78. 78. 79 BuildConfig Config BootStrap DataSource UrlMappings Tag Library Filter Domain Class View Controller Service Configuration MVC Spock, JUnit Testing
  79. 79. 80 1. grails.project.dependency.resolution = { 2. repositories { 3. grailsPlugins() 4. grailsHome() 5. mavenLocal() 6. grailsCentral() 7. mavenCentral() 8. } 9. dependencies { 10. runtime 'mysql:mysql-connector-java:5.1.29' 11. } 12. plugins { 13. build ":tomcat:7.0.54" ! 15. compile ":scaffolding:2.1.2" 16. compile ':cache:1.1.7' 17. compile ":asset-pipeline:1.8.11" ! 19. runtime ":hibernate4:4.3.5.4" 20. runtime ":database-migration:1.4.0" 21. runtime ":jquery:1.11.1" 22. } 23. } grails-app/conf/BuildConfig.groovy
  80. 80. 81 GORM Grails Object Relational Mapping DataSource.groovy RDBMS Domain Class
  81. 81. 82 grails create-domain-class User 1. class User { 2. String firstName 3. String lastName 4. Integer age 5. 6. static constraints = { 7. age range: 0..99 8. } 9. } 10.
  82. 82. 83 1. @TestFor(User) 2. class UserSpec extends Specification { 3. void "The new user must have first and last names"() { 4. when: 5. def user = new User() 6. then: 7. !user.validate() 8. when: 9. user = new User(firstName: 'John', lastName: 'Smith') 10. then: 11. user.validate() 12. } 13. } grails test-app
  83. 83. Test Report 84
  84. 84. 85 grails create-controller User 1. class UserController { 2. def index() { 3. redirect action: 'list' 4. } 5. def list() { 6. [ 7. users: User.list() 8. ] 9. } 10. }
  85. 85. 86 Views .gsp + = SiteMesh Layout .gsp Main content area and additional head tags. Theme, libraries and full page layout. Final HTML output to browsers. Decorated HTML TagLib Using custom tags in views.
  86. 86. 87 1. <!DOCTYPE html> 2. <html> 3. <head> 4. <meta name="layout" content="bootstrap3"/> 5. <title>…</title> 6. </head> 7. <body> 8. <p>Totals: ${users.size()}</p> 9. </body> 10. </html> grails-app/views/user/list.gsp SiteMesh
  87. 87. 88 1. <!DOCTYPE html> 2. <html> 3. <head> 4. <title>…</title> 5. <link rel="stylesheet" href="css/bootstrap.min.css"> 6. <link rel="stylesheet" href="css/bootstrap-theme.min.css"> 7. <script src="js/bootstrap.min.js"></script> 8. <g:layoutHead/> 9. </head> 10. <body> 11. <g:layoutBody/> 12. </body> 13. </html> grails-app/views/layout/bootstrap3.gsp
  88. 88. 89 1. class BootstrapTagLib { 2. static namespace = "bs3" 3. def alert = { attrs, body -> 4. out << """<div class="alert alert-${attrs.type?:'success'}">""" 5. out << body() 6. out << '</div>' 7. } 8. } 9. 1. <bs3:alert type="warning">Warning messages.</bs3:alert> 2. 3. <!-- Outputs: 4. <div class="alert alert-warning”>Warning messages.</div> 5. -->
  89. 89. 90 http://localhost:8080/project/controller/action/ID Default URL Mapping 1. class UserController { 2. def show(long id) { 3. [user: User.get(id)] 4. } 5. } …/user/show/1
  90. 90. 91 localhost:8080/user/list.html 1. class UserController { 2. … 3. def list() { 4. def users = User.list() 5. withFormat { 6. html users: users 7. xml { render users as XML } 8. json { render users as JSON } 9. } 10. } 11. } localhost:8080/user/list.xml localhost:8080/user/list.json Multiple Response Content-Type
  91. 91. Grails Application Packaging 92 grails war
  92. 92. 93 Grails Web Application Elastic Beanstalk RDS EC2 project-1.0.war Database 1. MySQL 2. PostgreSQL 3. Oracle 4. SQL Server Pre-configured VMs 1. Linux 2. Java 3. Tomcat Virtual Machine
  93. 93. Install Elastic Beanstalk Plugin 94 1. grails.project.dependency.resolution = { 2. … 3. plugins { 4. … 5. compile ':aws-elastic-beanstalk:0.3' 6. } 7. } 8. grails-app/conf/BuildConfig.groovy
  94. 94. Setup Elastic Beanstalk Plugin 95 grails-app/conf/Config.groovy 1. grails { 2. plugin { 3. awsElasticBeanstalk { 4. applicationName = 'myApplication' 5. environmentName = 'myEnvironment' 6. savedConfigurationName = 'default' 7. systemProperties = [ 8. 'property.name.1': 'property-value-1', 9. 'property.name.2': 'property-value-2'] 10. } 11. } 12. } 13.
  95. 95. 96 grails-app/conf/Config.groovy 1. environments { 2. production { 3. grails.logging.jul.usebridge = false 4. grails.serverURL = "http://{environment_ name}.elasticbeanstalk.com" 5. } 6. } 7.
  96. 96. 97 grails-app/conf/DataSource.groovy 1. production { 2. dataSource { 3. username = "{user}" 4. password = "{password}" 5. pooled = true 6. dbCreate = "update" 7. driverClassName = "com.mysql.jdbc.Driver" 8. url = "jdbc:mysql://{endpoint}:{port_number}/ebdb" 9. dialect = org.hibernate.dialect.MySQL5InnoDBDialect 10. properties { 11. validationQuery = "SELECT 1" 12. testOnBorrow = true 13. testOnReturn = true 14. testWhileIdle = true 15. timeBetweenEvictionRunsMillis = 1800000 16. numTestsPerEvictionRun = 3 17. minEvictableIdleTimeMillis = 1800000 18. } 19. } 20. } 21. xxxxxxxxxxxxxxx
  97. 97. ! 2. dataSource { ! 4. def prop = System.properties ! 6. username = "${prop.RDS_USERNAME}" 7. password = "${prop.RDS_PASSWORD}" ! 9. url = "jdbc:mysql://${prop.RDS_HOSTNAME}:${prop.RDS_PORT}/ebdb" 10. … 11. } 12. 98 1. RDS_USERNAME 2. RDS_PASSWORD 3. RDS_HOSTNAME 4. RDS_PORT 5. RDS_DB_NAME RDS System Properties
  98. 98. Deploy to Elastic Beanstalk 99 grails aws-eb-deploy
  99. 99. 100 EC2 Instance Load Balancer Amazon CloudFront Amazon S3 Bucket Web Application Server Assets (CSS, JavaScript, Images) CDN (Content delivery network) Deploy Grails web application assets to S3 and CloudFront.
  100. 100. CDN Asset Pipeline Grails Plugin 101 1. grails.project.dependency.resolution = { 2. … 3. plugins { 4. … 5. compile ':cdn-asset-pipeline:0.3.5' 6. } 7. } 8. grails-app/conf/BuildConfig.groovy
  101. 101. CDN Asset Pipeline Grails Plugin 102 1. grails { 2. assets { 3. cdn { 4. provider = 's3' 5. directory = 'my-bucket' 6. accessKey = '{MY_S3_ACCESS_KEY}' 7. secretKey = '{MY_S3_SECRET_KEY}' 8. storagePath = "assets/${appName}-${appVersion}/" 9. expires = 365 10. gzip = true 11. } 12. } 13. } 14. grails-app/conf/Config.groovy Use the {version} value to prevent outdated CDN cache.
  102. 102. Use CDN-based Assets 103 1. // S3 Only 2. grails.assets.url = "https://{bucketName}.s3.amazonaws.com/
 my-bucket/assets/${appName}-${appVersion}” 3. 4. // S3 + CloudFront 5. grails.assets.url = "https://{identity}.cloudfront.net/
 my-bucket/assets/${appName}-${appVersion}" 6. grails-app/conf/Config.groovy
  103. 103. 104 Use Groovy, Gradle or Grails for your next project.
  104. 104. Learn More 105 Search CodeData+Groovy
  105. 105. 106 THANK YOU lyhcode@gmail.com Q&A

×