gr8conf 2009: griffon by jim shingler

50
© Jim Shingler Introduction to Creating a Griffon: Rich Client front-end to our Twitter Clone By Jim Shingler 1 Wednesday, May 13, 2009

Upload: gr8conf

Post on 10-May-2015

1.934 views

Category:

Business


0 download

DESCRIPTION

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

TRANSCRIPT

Page 1: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Introduction toCreating a Griffon: Rich Client front-end to our

Twitter Clone

By Jim Shingler

1Wednesday, May 13, 2009

Page 2: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

AbstractGroovy 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.

2Wednesday, May 13, 2009

Page 3: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

IntroductionMy 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 Author3Wednesday, May 13, 2009

Page 4: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Agenda

</xml>

Griffon 101•What is Griffon•Installing Griffon•0 -100 k/mph in 60 seconds•Plugins Overview•Teaching the Griffon to count (Binding and Threading)•Readying Graeme’s Twitter Clone

Griffon 201•Griffon Twitter Client

4Wednesday, May 13, 2009

Page 5: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

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

5Wednesday, May 13, 2009

Page 6: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

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

6Wednesday, May 13, 2009

Page 7: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

DEMO

7Wednesday, May 13, 2009

Page 8: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Congratulations

Developer

you are a

8Wednesday, May 13, 2009

Page 9: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Griffon

Don’t forget to update your

resume.

9Wednesday, May 13, 2009

Page 10: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

App Structure& Convention

A pretty standard application structure, . . . you can pretty well guess the purpose of the files and

directories.

10Wednesday, May 13, 2009

Page 11: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Griffon Commands

11Wednesday, May 13, 2009

Page 12: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Plugins

12Wednesday, May 13, 2009

Page 13: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Start Small

• Swing and SwingX Builder

• GUI Components

• About Box

• Define and Process Actions

13Wednesday, May 13, 2009

Page 14: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

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

14Wednesday, May 13, 2009

Page 15: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Controllerimport 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')

}}

15Wednesday, May 13, 2009

Page 16: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Modelimport groovy.beans.Bindable

@Bindableclass CountingModel { def count = 0}

Adds Property Change Support

to the model

16Wednesday, May 13, 2009

Page 17: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

View and MenuView

application(title:'sample2', /*size:[320,480], */location:[200,200], pack:true, locationByPlatform:false) { // add content here build(Actions) build(MenuBar) button(id:'clickButton', text:bind{ model.count }, action: clickAction)}

jxmenuBar { menu(text: 'File', mnemonic: 'F') { menuItem(exitAction) }

glue() menu(text: 'Help', mnemonic: 'H') { menuItem(aboutAction) }}

MenuBar

Loads and runs Actions and MenuBar scripts inline

Use the action to define the menu item

Data Binding. Observe the change in the model

Execute the “clickAction”

17Wednesday, May 13, 2009

Page 18: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Actions// create the actionsaction(id: 'clickAction', name: 'Click Me', 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' )

Closure to run when the action is

executed

18Wednesday, May 13, 2009

Page 19: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Threading the GUI

It isn’t that bad

19Wednesday, May 13, 2009

Page 20: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

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

20Wednesday, May 13, 2009

Page 21: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Griffon Threading

• Build the UI in the EDTSwingBuilder.build { . . . }

• Long Running code outside the EDTdoOutside { . . . }

• code inside the EDTedt { . . . }doLater { . . . }

Creates thread and runs closure

Do synchronously in EDT

Do asynchronously in EDT

21Wednesday, May 13, 2009

Page 22: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

DEMO

22Wednesday, May 13, 2009

Page 23: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Model

import groovy.beans.Bindable

@Bindableclass CountingModel { def count = 0 def countSlow = 0 def countConcurrent = 0}

23Wednesday, May 13, 2009

Page 24: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Viewapplication(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})}

24Wednesday, May 13, 2009

Page 25: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Actions// create the actionsaction(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' )

25Wednesday, May 13, 2009

Page 26: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Controllerimport javax.swing.JOptionPaneclass 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''') }}

26Wednesday, May 13, 2009

Page 27: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Twitter Clone Enhancements

27Wednesday, May 13, 2009

Page 28: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Render Status XMLimport 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)} } }. . .

28Wednesday, May 13, 2009

Page 29: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

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 } } }

. . .

29Wednesday, May 13, 2009

Page 30: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

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] }

30Wednesday, May 13, 2009

Page 31: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Acegi Basic Authentication

grails-app/conf/SecurityConfig.groovysecurity {

// see DefaultSecurityConfig.groovy for all settable/overridable properties

active = true basicProcessingFilter = true

loginUserDomainClass = "Person" authorityDomainClass = "Authority" requestMapClass = "Requestmap"

}

31Wednesday, May 13, 2009

Page 32: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Acegi Basic Authentication

beans = { authenticationEntryPoint(org.springframework.security.ui.basicauth. BasicProcessingFilterEntryPoint) { realmName = 'Grails Realm' } twitterCache(org.springframework.cache.ehcache.EhCacheFactoryBean) { timeToLive = 1200 } }

grails-app/conf/spring/resources.groovy

32Wednesday, May 13, 2009

Page 33: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Griffon Twitter Clone Client

33Wednesday, May 13, 2009

Page 34: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Requirements

• Login

• Display User Info

• Display Statuses (Tweets)

• Update Statuses(Tweets)

• Send My Own Status (Tweet)

34Wednesday, May 13, 2009

Page 35: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Overview

Twitter Clone

Twitter Service

ViewController

Model

MenuBar

ToolBar

StatusBar

Tips

About

MVC Triad

</xml>

35Wednesday, May 13, 2009

Page 36: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Let’s get to Work

36Wednesday, May 13, 2009

Page 37: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

ToolBar

User Info

Statuses / Tweets

RefreshLogin

Update Status

37Wednesday, May 13, 2009

Page 38: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

38Wednesday, May 13, 2009

Page 39: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Other Griffon Apps

39Wednesday, May 13, 2009

Page 40: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

40Wednesday, May 13, 2009

Page 41: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

41Wednesday, May 13, 2009

Page 42: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

42Wednesday, May 13, 2009

Page 43: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

43Wednesday, May 13, 2009

Page 44: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

44Wednesday, May 13, 2009

Page 45: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

45Wednesday, May 13, 2009

Page 46: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

The Codehttp://github.com/jshingler/gr8conf_2009/tree/master

46Wednesday, May 13, 2009

Page 47: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Founders

Danno Ferrinhttp://shemnon.com/speling

Andres Almirayhttp://jroller.com/aalmiray

James Williamshttp://jameswilliams.be/blog

47Wednesday, May 13, 2009

Page 48: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Resources•Griffon• griffon.codehause.org• [email protected]•Grails•www.grails.org•Books Coming

Soon

48Wednesday, May 13, 2009

Page 49: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Resources•[email protected] is a medium volume list

useful for those interested in ongoing developments• [email protected] is a high volume list

that logs commits and issues•[email protected] 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.

49Wednesday, May 13, 2009

Page 50: GR8Conf 2009: Griffon by Jim Shingler

© Jim Shingler

Conclusion

• Blog: http://jshingler.blogspot.com

• Email: [email protected]

• LinkedIn: http://www.linkedin.com/in/jimshingler

• Twitter: @jshingler

Thank You for your time

50Wednesday, May 13, 2009