GR8Conf 2009: Griffon by Jim Shingler

2,016
-1

Published on

Jim Shingler presents an introduction to the Griffon Swing MVC framework.

Published in: Business, Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,016
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
84
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

GR8Conf 2009: Griffon by Jim Shingler

  1. 1. Introduction to Creating a Griffon: Rich Client front-end to our Twitter Clone By Jim Shingler © Jim Shingler Wednesday, May 13, 2009 1
  2. 2. Abstract Groovy and Grails have given us the ability to leverage the strength of the Java Platform (and Eco System) and the productivity of “Convention over Configuration” to construct websites. But “What If” the User Interface requirements of the new application is best solved with the type of interaction a desktop application provides? Griffon bring the same productivity gains to the desktop application that Grails brings to web applications. This session will use Griffon and popular open source libraries to build a desktop application to interact with a Grails backend. © Jim Shingler Wednesday, May 13, 2009 2
  3. 3. Introduction My name is Jim Shingler Chief Technical Architect President of Genuine Solutions Beginning Groovy and Grails Co-Author FallME (Inversion of Control for JavaME) Co-Founder Griffon Splash Plugin Author Griffon gConfig Author Griffon TM Bundle Author © Jim Shingler Wednesday, May 13, 2009 3
  4. 4. Agenda Griffon 101 •What is Griffon •Installing Griffon •0 -100 k/mph in 60 seconds </xml> •Plugins Overview •Teaching the Griffon to count (Binding and Threading) •Readying Graeme’s Twitter Clone Griffon 201 •Griffon Twitter Client © Jim Shingler Wednesday, May 13, 2009 4
  5. 5. Installing Griffon 1. Download Griffon 2. Unpack it (unix: /opt/local/share/ windows: /apps/griffon) 3. Set the GROOVY_HOME 4. Add it to your path, <GROOVY_HOME>/bin © Jim Shingler Wednesday, May 13, 2009 5
  6. 6. 0-100 k/mph in 60 Seconds > griffon create-app small Welcome to Griffon 0.1.0 - http://griffon.codehaus.org/ Licensed under Apache Standard License 2.0 Griffon home is set to: /opt/local/share/griffon-0.1.0 ... > griffon run-app © Jim Shingler Wednesday, May 13, 2009 6
  7. 7. DEMO © Jim Shingler Wednesday, May 13, 2009 7
  8. 8. Congratulations you are a Developer © Jim Shingler Wednesday, May 13, 2009 8
  9. 9. Don’t forget to update your resume. Griffon © Jim Shingler Wednesday, May 13, 2009 9
  10. 10. App Structure & Convention A pretty standard application structure, . . . you can pretty well guess the purpose of the files and directories. © Jim Shingler Wednesday, May 13, 2009 10
  11. 11. Griffon Commands © Jim Shingler Wednesday, May 13, 2009 11
  12. 12. Plugins © Jim Shingler Wednesday, May 13, 2009 12
  13. 13. Start Small • Swing and SwingX Builder • GUI Components • About Box • Define and Process Actions © Jim Shingler Wednesday, May 13, 2009 13
  14. 14. DEMO • Create Count App • Add Button • Build and Initialize “Click Action” • Process the Click Action • Install and Enable SwingXBuilder • Build and Initialize Menus • Build and Initialize “Menu Actions” • Process the Menu Actions © Jim Shingler Wednesday, May 13, 2009 14
  15. 15. Controller import javax.swing.JOptionPane class CountingController { // these will be injected by Griffon def model def view def builder void mvcGroupInit(Map args) { // this method is called after model and view are injected } def click = { evt = null -> model.count++ } def exit = { evt = null -> app.shutdown() } def showAbout = { evt = null -> builder.optionPane().showMessageDialog(null, 'This is the Counting Application') } } © Jim Shingler Wednesday, May 13, 2009 15
  16. 16. Model import groovy.beans.Bindable Adds Property @Bindable Change Support class CountingModel { def count = 0 } to the model © Jim Shingler Wednesday, May 13, 2009 16
  17. 17. View and Menu View application(title:'sample2', /*size:[320,480], */location:[200,200], pack:true, locationByPlatform:false) { // add content here build(Actions) Loads and runs Actions and MenuBar scripts inline build(MenuBar) button(id:'clickButton', text:bind{ model.count }, action: clickAction) } Data Binding. Observe the change in the model MenuBar Execute the “clickAction” jxmenuBar { menu(text: 'File', mnemonic: 'F') { menuItem(exitAction) Use the action to define } the menu item glue() menu(text: 'Help', mnemonic: 'H') { menuItem(aboutAction) } } © Jim Shingler Wednesday, May 13, 2009 17
  18. 18. Actions // create the actions Closure to run when action(id: 'clickAction', the action is name: 'Click Me', executed closure: controller.&click, shortDescription: 'Increment the Click Count' ) action(id: 'exitAction', name: 'Exit', closure: controller.exit, mnemonic: 'x', accelerator: 'F4', shortDescription: 'Exit SimpleUI' ) action(id: 'aboutAction', name: 'About', closure: controller.showAbout, mnemonic: 'A', accelerator: 'F1', shortDescription: 'Find out about SimpleUI' ) © Jim Shingler Wednesday, May 13, 2009 18
  19. 19. Threading the GUI It isn’t that bad © Jim Shingler Wednesday, May 13, 2009 19
  20. 20. Rules of Thumb • Painting and UI Operations need to be done in the EventDispatchThread (EDT) • Everything else should be done outside the EDT • Java 6 has SwingWorker, Java 5 has SwingLabs Swingworker But that just isn’t Groovy enough for Griffon © Jim Shingler Wednesday, May 13, 2009 20
  21. 21. Griffon Threading • Build the UI in the EDT SwingBuilder.build { . . . } • Long Running code outside the EDT doOutside { . . . } Creates thread and runs closure • code inside the EDT edt { . . . } Do synchronously in EDT doLater { . . . } Do asynchronously in EDT © Jim Shingler Wednesday, May 13, 2009 21
  22. 22. DEMO © Jim Shingler Wednesday, May 13, 2009 22
  23. 23. Model import groovy.beans.Bindable @Bindable class CountingModel { def count = 0 def countSlow = 0 def countConcurrent = 0 } © Jim Shingler Wednesday, May 13, 2009 23
  24. 24. View application(title:'counting', /*size:[320,480], location:[50,50],*/ pack:true, locationByPlatform:true) { build(Actions) build(MenuBar) gridLayout() button(id:'clickButton', text:bind {model.count}, action: clickAction) label(text:bind {model.count}) button(id:'slowClickButton', text:"Slow Click", action: slowClickAction) label(text:bind {model.countSlow}) button(id:'concurrentClickButton', text:"Concurrent Click", action: concurrentClickAction) label(text:bind {model.countConcurrent}) } © Jim Shingler Wednesday, May 13, 2009 24
  25. 25. Actions // create the actions action(id: 'clickAction', name: 'Click', closure: controller.&click, shortDescription: 'Increment the Click Count' ) action(id: 'clickActionSlow', name: 'Click Slow', closure: controller.&clickSlow, shortDescription: 'Increment the Click Count Slow' ) action(id: 'clickActionConcurrent', name: 'Click Concurrent', closure: controller.&clickConcurrent, shortDescription: 'Increment the Click Count Concurrent' ) action(id: 'exitAction', name: 'Exit', closure: controller.exit, mnemonic: 'x', accelerator: 'F4', shortDescription: 'Exit SimpleUI' ) action(id: 'aboutAction', name: 'About', closure: controller.showAbout, mnemonic: 'A', accelerator: 'F1', shortDescription: 'Find out about SimpleUI' ) © Jim Shingler Wednesday, May 13, 2009 25
  26. 26. Controller import javax.swing.JOptionPane class CountingController { // these will be injected by Griffon def model def view void mvcGroupInit(Map args) { } def click = { evt -> model.count++ } def clickSlow = { evt = null -> Thread.sleep(5000) model.countSlow++ } def clickConcurrent = { evt = null -> doOutside { Thread.sleep(5000) edt { // Sync model.countConcurrent++ } } } def exit = { evt = null -> System.exit(0) } def showAbout = { evt = null -> JOptionPane.showMessageDialog(null, '''This is the SimpleUI Application''') } } © Jim Shingler Wednesday, May 13, 2009 26
  27. 27. Twitter Clone Enhancements © Jim Shingler Wednesday, May 13, 2009 27
  28. 28. Render Status XML import grails.converters.* class StatusController { def twitterCache def index = { def messages = twitterCache.get(principalInfo.username)?.value if(!messages) { messages = findStatusMessages() twitterCache.put new Element(principalInfo.username, messages) } def feedOutput = { . . . } withFormat { html([messages:messages]) xml { render messages as XML} rss { render(feedType:"rss", feedOutput)} } } . . . © Jim Shingler Wednesday, May 13, 2009 28
  29. 29. Render Person XML import grails.converters.* class PersonController { ... def findByUsername = { def p = Person.findByUsername(params.username) withFormat { html person:p xml { render p as XML } } } ... © Jim Shingler Wednesday, May 13, 2009 29
  30. 30. def show = { def person = Person.get(params.id) if (!person) { flash.message = "Person not found with id $params.id" redirect action: list return } List roleNames = [] for (role in person.authorities) { roleNames << role.authority } roleNames.sort { n1, n2 -> n1 <=> n2 } withFormat { html ( [person: person, roleNames: roleNames] ) xml { render person as XML } } // [person: person, roleNames: roleNames] } © Jim Shingler Wednesday, May 13, 2009 30
  31. 31. Acegi Basic Authentication grails-app/conf/SecurityConfig.groovy security { // see DefaultSecurityConfig.groovy for all settable/overridable properties active = true basicProcessingFilter = true loginUserDomainClass = "Person" authorityDomainClass = "Authority" requestMapClass = "Requestmap" } © Jim Shingler Wednesday, May 13, 2009 31
  32. 32. Acegi Basic Authentication grails-app/conf/spring/resources.groovy beans = { authenticationEntryPoint(org.springframework.security.ui.basicauth. BasicProcessingFilterEntryPoint) { realmName = 'Grails Realm' } twitterCache(org.springframework.cache.ehcache.EhCacheFactoryBean) { timeToLive = 1200 } } © Jim Shingler Wednesday, May 13, 2009 32
  33. 33. Griffon Twitter Clone Client © Jim Shingler Wednesday, May 13, 2009 33
  34. 34. Requirements • Login • Display User Info • Display Statuses (Tweets) • Update Statuses(Tweets) • Send My Own Status (Tweet) © Jim Shingler Wednesday, May 13, 2009 34
  35. 35. Overview MVC Triad MenuBar Controller View ToolBar StatusBar Model Tips About Twitter Service </xml> Twitter Clone © Jim Shingler Wednesday, May 13, 2009 35
  36. 36. Let’s get to Work © Jim Shingler Wednesday, May 13, 2009 36
  37. 37. Login Refresh ToolBar User Info Statuses / Tweets Update Status © Jim Shingler Wednesday, May 13, 2009 37
  38. 38. © Jim Shingler Wednesday, May 13, 2009 38
  39. 39. Other Griffon Apps © Jim Shingler Wednesday, May 13, 2009 39
  40. 40. © Jim Shingler Wednesday, May 13, 2009 40
  41. 41. © Jim Shingler Wednesday, May 13, 2009 41
  42. 42. © Jim Shingler Wednesday, May 13, 2009 42
  43. 43. © Jim Shingler Wednesday, May 13, 2009 43
  44. 44. © Jim Shingler Wednesday, May 13, 2009 44
  45. 45. © Jim Shingler Wednesday, May 13, 2009 45
  46. 46. The Code http://github.com/jshingler/gr8conf_2009/tree/master © Jim Shingler Wednesday, May 13, 2009 46
  47. 47. Founders Danno Ferrin http://shemnon.com/speling Andres Almiray http://jroller.com/aalmiray James Williams http://jameswilliams.be/blog © Jim Shingler Wednesday, May 13, 2009 47
  48. 48. Resources • Griffon • griffon.codehause.org • griffon-user@groovy.codehause.org • Grails • www.grails.org Coming • Books Soon © Jim Shingler Wednesday, May 13, 2009 48
  49. 49. Resources • dev@griffon.codehaus.org is a medium volume list useful for those interested in ongoing developments • scm@griffon.codehaus.org is a high volume list that logs commits and issues • user@griffon.codehaus.org is a high volume list is for questions and general discussion about Griffon • You can find a great archive support at MarkMail, http://griffon.markmail.org. © Jim Shingler Wednesday, May 13, 2009 49
  50. 50. Conclusion Thank You for your time • Blog: http://jshingler.blogspot.com • Email: ShinglerJim@gmail.com • LinkedIn: http://www.linkedin.com/in/jimshingler • Twitter: @jshingler © Jim Shingler Wednesday, May 13, 2009 50

×