SlideShare a Scribd company logo
Introduction to
                            Creating a Griffon: Rich Client front-end to our
                                             Twitter Clone

                                            By Jim Shingler




           © Jim Shingler

Wednesday, May 13, 2009                                                        1
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
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
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
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
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
DEMO
           © Jim Shingler

Wednesday, May 13, 2009            7
Congratulations
                            you are a




                            Developer

           © Jim Shingler

Wednesday, May 13, 2009                 8
Don’t
              forget to
                update
                 your
               resume.


                            Griffon



           © Jim Shingler

Wednesday, May 13, 2009               9
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
Griffon Commands




           © Jim Shingler

Wednesday, May 13, 2009                        11
Plugins




           © Jim Shingler

Wednesday, May 13, 2009               12
Start Small
                     • Swing and SwingX Builder
                     • GUI Components
                     • About Box
                     • Define and Process Actions


           © Jim Shingler

Wednesday, May 13, 2009                            13
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
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
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
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
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
Threading the GUI




                                It isn’t that bad
           © Jim Shingler

Wednesday, May 13, 2009                             19
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
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
DEMO

           © Jim Shingler

Wednesday, May 13, 2009            22
Model
                            import groovy.beans.Bindable

                            @Bindable
                            class CountingModel {
                                def count = 0
                                def countSlow = 0
                                def countConcurrent = 0
                            }




           © Jim Shingler

Wednesday, May 13, 2009                                    23
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
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
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
Twitter Clone
             Enhancements
           © Jim Shingler

Wednesday, May 13, 2009      27
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
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
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
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
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
Griffon Twitter
            Clone Client
           © Jim Shingler

Wednesday, May 13, 2009      33
Requirements

                     • Login
                     • Display User Info
                     • Display Statuses (Tweets)
                     • Update Statuses(Tweets)
                     • Send My Own Status (Tweet)
           © Jim Shingler

Wednesday, May 13, 2009                             34
Overview
                                MVC Triad
                                                 MenuBar
                       Controller         View
                                                 ToolBar

                                                 StatusBar
                                 Model             Tips

                                                  About

               Twitter Service

                            </xml>


                   Twitter Clone
           © Jim Shingler

Wednesday, May 13, 2009                                      35
Let’s get to
                              Work
           © Jim Shingler

Wednesday, May 13, 2009                    36
Login   Refresh   ToolBar

                                                    User Info



                                                  Statuses / Tweets




                    Update
                    Status




           © Jim Shingler

Wednesday, May 13, 2009                                               37
© Jim Shingler

Wednesday, May 13, 2009     38
Other Griffon
                  Apps
           © Jim Shingler

Wednesday, May 13, 2009        39
© Jim Shingler

Wednesday, May 13, 2009     40
© Jim Shingler

Wednesday, May 13, 2009     41
© Jim Shingler

Wednesday, May 13, 2009     42
© Jim Shingler

Wednesday, May 13, 2009     43
© Jim Shingler

Wednesday, May 13, 2009     44
© Jim Shingler

Wednesday, May 13, 2009     45
The Code
                     http://github.com/jshingler/gr8conf_2009/tree/master




           © Jim Shingler

Wednesday, May 13, 2009                                                     46
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
Resources
                • Griffon
                  • griffon.codehause.org
                  • griffon-user@groovy.codehause.org
                • Grails
                  • www.grails.org
                                                 Coming
                • Books                           Soon




           © Jim Shingler

Wednesday, May 13, 2009                                   48
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
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

More Related Content

PPT
What have you learnt from technologies from the process of construction the p...
PDF
GR8Conf 2011: Grails Infinispanplugin, Tom Fuller
PDF
GR8Conf 2011: Building Progressive UIs with Grails
PDF
GR8Conf 2011: Groovy 1.8 update
PDF
GR8Conf 2009: Industrial Strength Groovy by Paul King
PDF
GR8Conf 2011: Canoo RIA Suite
KEY
Grails EE
KEY
Groovy overview, DSLs and ecosystem - Mars JUG - 2010
What have you learnt from technologies from the process of construction the p...
GR8Conf 2011: Grails Infinispanplugin, Tom Fuller
GR8Conf 2011: Building Progressive UIs with Grails
GR8Conf 2011: Groovy 1.8 update
GR8Conf 2009: Industrial Strength Groovy by Paul King
GR8Conf 2011: Canoo RIA Suite
Grails EE
Groovy overview, DSLs and ecosystem - Mars JUG - 2010

Similar to GR8Conf 2009: Griffon by Jim Shingler (20)

PPT
Fast web development using groovy on grails
ODP
Groovygrailsnetbeans 12517452668498-phpapp03
KEY
groovy & grails - lecture 9
PDF
Griffon In Front Grails In Back
PDF
Java Edge.2009.Grails.Web.Dev.Made.Easy
PDF
Tomas Grails
PDF
Grails 101
ODP
JavaOne 2009 BOF-5189 Griffon In Depth
PDF
Grails @ Java User Group Silicon Valley
ODP
Griffon: Re-imaging Desktop Java Technology
PDF
Grailsx@ロンドンへ行ってきた報告。
PDF
Groovy Domain Specific Languages - SpringOne2GX 2012
PDF
Griffon for the Enterprise
PDF
Paulking groovy
PDF
Groovy Power Features
PPT
Devoxx - Flying with Griffon
PPT
Griffon - Making Swing Fun Again
PDF
Groovy & Grails for Spring/Java developers
PDF
XML-Free Programming : Java Server and Client Development without &lt;>
PPTX
Groovy And Grails Introduction
Fast web development using groovy on grails
Groovygrailsnetbeans 12517452668498-phpapp03
groovy & grails - lecture 9
Griffon In Front Grails In Back
Java Edge.2009.Grails.Web.Dev.Made.Easy
Tomas Grails
Grails 101
JavaOne 2009 BOF-5189 Griffon In Depth
Grails @ Java User Group Silicon Valley
Griffon: Re-imaging Desktop Java Technology
Grailsx@ロンドンへ行ってきた報告。
Groovy Domain Specific Languages - SpringOne2GX 2012
Griffon for the Enterprise
Paulking groovy
Groovy Power Features
Devoxx - Flying with Griffon
Griffon - Making Swing Fun Again
Groovy & Grails for Spring/Java developers
XML-Free Programming : Java Server and Client Development without &lt;>
Groovy And Grails Introduction
Ad

More from GR8Conf (20)

PDF
DevOps Enabling Your Team
PDF
Creating and testing REST contracts with Accurest Gradle
PDF
Mum, I want to be a Groovy full-stack developer
PDF
Metaprogramming with Groovy
PDF
Scraping with Geb
PDF
How to create a conference android app with Groovy and Android
PDF
Ratpack On the Docks
PDF
Groovy Powered Clean Code
PDF
Cut your Grails application to pieces - build feature plugins
PDF
Performance tuning Grails applications
PDF
Ratpack and Grails 3
PDF
Grails & DevOps: continuous integration and delivery in the cloud
PDF
Functional testing your Grails app with GEB
PDF
Deploying, Scaling, and Running Grails on AWS and VPC
PDF
The Grails introduction workshop
PDF
Idiomatic spock
PDF
The Groovy Ecosystem Revisited
PDF
Groovy 3 and the new Groovy Meta Object Protocol in examples
PDF
Integration using Apache Camel and Groovy
PDF
CRaSH the shell for the Java Virtual Machine
DevOps Enabling Your Team
Creating and testing REST contracts with Accurest Gradle
Mum, I want to be a Groovy full-stack developer
Metaprogramming with Groovy
Scraping with Geb
How to create a conference android app with Groovy and Android
Ratpack On the Docks
Groovy Powered Clean Code
Cut your Grails application to pieces - build feature plugins
Performance tuning Grails applications
Ratpack and Grails 3
Grails & DevOps: continuous integration and delivery in the cloud
Functional testing your Grails app with GEB
Deploying, Scaling, and Running Grails on AWS and VPC
The Grails introduction workshop
Idiomatic spock
The Groovy Ecosystem Revisited
Groovy 3 and the new Groovy Meta Object Protocol in examples
Integration using Apache Camel and Groovy
CRaSH the shell for the Java Virtual Machine
Ad

Recently uploaded (20)

PPT
Lecture 3344;;,,(,(((((((((((((((((((((((
PDF
Building a Smart Pet Ecosystem: A Full Introduction to Zhejiang Beijing Techn...
PDF
Nante Industrial Plug Factory: Engineering Quality for Modern Power Applications
PDF
ANALYZING THE OPPORTUNITIES OF DIGITAL MARKETING IN BANGLADESH TO PROVIDE AN ...
PDF
SIMNET Inc – 2023’s Most Trusted IT Services & Solution Provider
PDF
NISM Series V-A MFD Workbook v December 2024.khhhjtgvwevoypdnew one must use ...
PPTX
operations management : demand supply ch
PPTX
Slide gioi thieu VietinBank Quy 2 - 2025
PPTX
2025 Product Deck V1.0.pptxCATALOGTCLCIA
PPTX
Sales & Distribution Management , LOGISTICS, Distribution, Sales Managers
PDF
How to Get Approval for Business Funding
PDF
How to Get Business Funding for Small Business Fast
PDF
How to Get Funding for Your Trucking Business
PDF
Module 2 - Modern Supervison Challenges - Student Resource.pdf
PDF
Blood Collected straight from the donor into a blood bag and mixed with an an...
PDF
NewBase 12 August 2025 Energy News issue - 1812 by Khaled Al Awadi_compresse...
PDF
IFRS Notes in your pocket for study all the time
PPTX
3. HISTORICAL PERSPECTIVE UNIIT 3^..pptx
PDF
pdfcoffee.com-opt-b1plus-sb-answers.pdfvi
PDF
Tata consultancy services case study shri Sharda college, basrur
Lecture 3344;;,,(,(((((((((((((((((((((((
Building a Smart Pet Ecosystem: A Full Introduction to Zhejiang Beijing Techn...
Nante Industrial Plug Factory: Engineering Quality for Modern Power Applications
ANALYZING THE OPPORTUNITIES OF DIGITAL MARKETING IN BANGLADESH TO PROVIDE AN ...
SIMNET Inc – 2023’s Most Trusted IT Services & Solution Provider
NISM Series V-A MFD Workbook v December 2024.khhhjtgvwevoypdnew one must use ...
operations management : demand supply ch
Slide gioi thieu VietinBank Quy 2 - 2025
2025 Product Deck V1.0.pptxCATALOGTCLCIA
Sales & Distribution Management , LOGISTICS, Distribution, Sales Managers
How to Get Approval for Business Funding
How to Get Business Funding for Small Business Fast
How to Get Funding for Your Trucking Business
Module 2 - Modern Supervison Challenges - Student Resource.pdf
Blood Collected straight from the donor into a blood bag and mixed with an an...
NewBase 12 August 2025 Energy News issue - 1812 by Khaled Al Awadi_compresse...
IFRS Notes in your pocket for study all the time
3. HISTORICAL PERSPECTIVE UNIIT 3^..pptx
pdfcoffee.com-opt-b1plus-sb-answers.pdfvi
Tata consultancy services case study shri Sharda college, basrur

GR8Conf 2009: Griffon by Jim Shingler

  • 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. 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. 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. 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. 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. 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. DEMO © Jim Shingler Wednesday, May 13, 2009 7
  • 8. Congratulations you are a Developer © Jim Shingler Wednesday, May 13, 2009 8
  • 9. Don’t forget to update your resume. Griffon © Jim Shingler Wednesday, May 13, 2009 9
  • 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. Griffon Commands © Jim Shingler Wednesday, May 13, 2009 11
  • 12. Plugins © Jim Shingler Wednesday, May 13, 2009 12
  • 13. Start Small • Swing and SwingX Builder • GUI Components • About Box • Define and Process Actions © Jim Shingler Wednesday, May 13, 2009 13
  • 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. 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. 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. 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. 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. Threading the GUI It isn’t that bad © Jim Shingler Wednesday, May 13, 2009 19
  • 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. 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. DEMO © Jim Shingler Wednesday, May 13, 2009 22
  • 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. 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. 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. 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. Twitter Clone Enhancements © Jim Shingler Wednesday, May 13, 2009 27
  • 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. 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. 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. 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. 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. Griffon Twitter Clone Client © Jim Shingler Wednesday, May 13, 2009 33
  • 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. Overview MVC Triad MenuBar Controller View ToolBar StatusBar Model Tips About Twitter Service </xml> Twitter Clone © Jim Shingler Wednesday, May 13, 2009 35
  • 36. Let’s get to Work © Jim Shingler Wednesday, May 13, 2009 36
  • 37. Login Refresh ToolBar User Info Statuses / Tweets Update Status © Jim Shingler Wednesday, May 13, 2009 37
  • 38. © Jim Shingler Wednesday, May 13, 2009 38
  • 39. Other Griffon Apps © Jim Shingler Wednesday, May 13, 2009 39
  • 40. © Jim Shingler Wednesday, May 13, 2009 40
  • 41. © Jim Shingler Wednesday, May 13, 2009 41
  • 42. © Jim Shingler Wednesday, May 13, 2009 42
  • 43. © Jim Shingler Wednesday, May 13, 2009 43
  • 44. © Jim Shingler Wednesday, May 13, 2009 44
  • 45. © Jim Shingler Wednesday, May 13, 2009 45
  • 46. The Code http://github.com/jshingler/gr8conf_2009/tree/master © Jim Shingler Wednesday, May 13, 2009 46
  • 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. 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. 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. 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