Griffon In Front Grails In Back
Upcoming SlideShare
Loading in...5
×
 

Griffon In Front Grails In Back

on

  • 13,886 views

 

Statistics

Views

Total Views
13,886
Views on SlideShare
13,690
Embed Views
196

Actions

Likes
13
Downloads
255
Comments
0

5 Embeds 196

http://www.grails66.com 132
http://www.slideshare.net 51
https://twimg0-a.akamaihd.net 7
http://www.linkedin.com 4
https://si0.twimg.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Griffon In Front Grails In Back Griffon In Front Grails In Back Presentation Transcript

  • Griffon in Front Grails in Back Leveraging Grails with Griffon
  • Griffon in Front Grails in Back Leveraging Grails with Griffon
  • 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 applicaiton to interact with a Grails backend.
  • 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 Founders
  • Griffon Founders Danno Ferrin http://shemnon.com/speling Andres Almiray http://jroller.com/aalmiray James Williams http://jameswilliams.be/blog
  • Common Complaints about Swing Its hard Have to code too much Code is complex Not many Advanced GUI Components (Myth)
  • Start Small • Swing and SwingX Builder • GUI Components • About Box • Define and Process Actions
  • Builders The Builder Pattern is a software design pattern. The intention is to separate the construction of a complex object from its representation so that the same construction process can create different representations. Often, the Build Patter is used to build Products in accordance to the Composite pattern. Swing is a complex hierarchy, . . . Source: Wikipedia Sounds like an opportunity
  • GUI Builders • SwingBuilder Applies the Builder Pattern to the construction of Swing “Makes Swing Groovy” • SwingXBuilder Extends SwingBuilder adding the SwingLabs Components • JideBuilder Extends SwingBuilder adding JIDE Components • SWTBuilder Applies the Builder Pattern to the construction of SWT “Makes SWT Groovy”
  • Plugins A plugin is a Griffon extension point. Conceptually, it is similar to the plugins found in modern IDEs. A plugin is a technique to encapsulate functionality that can be reused across multiple applications. Griffon’s plugin community has just begun but it is growing fast. See: >griffon list-plugins http://grails.org/Plugins http://www.grails.org/The+Plug-in+Developers+Guide
  • 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
  • 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 NOTE: The Code included on the next several pages has been enhanced based upon questions asked in the session.
  • Controller import javax.swing.JOptionPane class Sample2Controller { // these will be injected by Griffon def model def view void mvcGroupInit(Map args) { // this method is called after model and view are injected } def click = { evt = null -> model.count++ } def exit = { evt = null -> System.exit(0) } def showAbout = { evt = null -> JOptionPane.showMessageDialog(null, '''This is the SimpleUI Application''') } }
  • Model import groovy.beans.Bindable @Bindable class Sample2Model { def count = 0 }
  • View 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) } MenuBar jxmenuBar { menu(text: 'File', mnemonic: 'F') { menuItem(exitAction) } glue() menu(text: 'Help', mnemonic: 'H') { menuItem(aboutAction) } }
  • Actions // create the actions action(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' )
  • Goal
  • Goal Menu Bar Tool Bar Content Area Status Bar
  • Goal Menu Bar Tool Bar Login Dialog Content Area Tips Dialog Status Bar
  • Planning • Menu Bar • Tool Bar • Status Bar • About Box • Tips • Login Dialog • Master / Detail Content Area •Table and Fields • Wire it together with Actions • Make calls to Web Services
  • Planning • Menu Bar  • Tool Bar • Status Bar • About Box • Tips • Login Dialog • Master / Detail Content Area •Table and Fields • Wire it together with Actions • Make calls to Web Services
  • Planning • Menu Bar  • Tool Bar • Status Bar • About Box • Tips • Login Dialog • Master / Detail Content Area •Table and Fields • Wire it together with Actions • Make calls to Web Services
  • Planning • Menu Bar  • Tool Bar • Status Bar • About Box  • Tips • Login Dialog • Master / Detail Content Area •Table and Fields • Wire it together with Actions • Make calls to Web Services
  • Planning • Menu Bar  • Tool Bar • Status Bar • About Box  • Tips • Login Dialog • Master / Detail Content Area •Table and Fields • Wire it together with Actions • Make calls to Web Services
  • Planning • Menu Bar  • Tool Bar • Status Bar • About Box  • Tips • Login Dialog • Master / Detail Content Area Glazed Lists •Table and Fields • Wire it together with Actions • Make calls to Web Services
  • Planning • Menu Bar  • Tool Bar • Status Bar • About Box  • Tips • Login Dialog • Master / Detail Content Area Glazed Lists •Table and Fields • Wire it together with Actions • Make calls to Web Services
  • Planning • Menu Bar  • Tool Bar • Status Bar • About Box  • Tips • Login Dialog • Master / Detail Content Area Glazed Lists •Table and Fields • Wire it together with Actions  • Make calls to Web Services
  • Planning • Menu Bar  • Tool Bar • Status Bar • About Box  • Tips • Login Dialog • Master / Detail Content Area Glazed Lists •Table and Fields • Wire it together with Actions  • Make calls to Web Services
  • Organization MVC Triad Controller View Model
  • Organization MVC Triad Controller View Model Griffon Framework
  • Organization Controller View Model Griffon Framework
  • Organization Menu Bar Controller View Model Griffon Framework
  • Organization Menu Bar Controller View About Dialog Model Griffon Framework
  • Organization Menu Bar Controller View About Dialog Content Pane Model Griffon Framework
  • Organization Menu Bar Controller View About Dialog Content Pane Model Tool Bar Griffon Framework
  • Organization Menu Bar Controller View About Dialog Content Pane Model Tool Bar Status Bar Griffon Framework
  • Organization Menu Bar Controller View About Dialog Content Pane Model Tool Bar Services Status Bar Griffon Framework
  • Organization Menu Bar Controller View About Dialog Content Pane Model Tool Bar Services Status Bar Http Utils Get Griffon Framework Put Post Delete
  • Organization Menu Bar Controller View About Dialog Content Pane Model Tool Bar Services Status Bar Http Utils Get Griffon Framework Put Post Delete Rest Controller
  • Interaction with RESTful WebServices SQL HTTP Grails Action Method Method Convention Create INSERT PUT create Read SELECT GET show Update UPDATE POST update Delete DELETE DELETE delete Collect SELECT list
  • Loading Data class GCollabTodoController { ... void loadData() { setStatus(quot;Loading Dataquot;) busy model.todos.clear() model.todos.addAll (TodoService.list(appContext)) norm setStatus(quot;Finished Loading Dataquot;) } class TodoService { static String APP_URL = 'http://localhost:8080/collab-todo/json/todo' static List list(appContext) { def userContext = appContext.userContext def get = new Get(url: APP_URL, userName: userContext.userName, password: userContext.password) def todoJson = get.text def str = JsonUtil.makeJSONStrict(todoJson) def jsonarray = JSONSerializer.toJSON(str) def todo def outputList = [] jsonarray.each { todo = JsonUtil.jsonToObject(it.toString(), Todo.class) outputList.add todo } return outputList }
  • Let’s Look at the Code
  • class Get{ String url QueryString queryString = new QueryString() String text Get (HttpUtils) def userName def password String getText() try { def response def conn = new URL(toString()).openConnection() conn.requestMethod = quot;GETquot; conn.doOutput = true if (userName && password) { conn.setRequestProperty(quot;Authorizationquot;, quot;Basic ${userName}:${password}quot;) } def content if (conn.responseCode == conn.HTTP_OK) { response = conn.content.text } else { response = quot;URL: quot; + this.toString() + quot;nquot; + quot;RESPONSE CODE: quot; + conn.responseCode throw new ResourceException(response) } conn.disconnect() return response } catch (Exception e) { println quot;Caught Exception ${e}quot; throw new ResourceException(e) } } String toString(){ return url + quot;?quot; + queryString.toString() }
  • Save Todo void saveTodo(event) { fillSelectedTodoFromView() def todo = selectedTodo() if(shouldBeSaved(todo)) { execWithExceptionHandling { TodoService.save(appContext, todo) loadData() } } else { JOptionPane.showMessageDialog(frame, quot;If this had been a completed application the Todo would have been updated:quot;) } } private boolean shouldBeSaved(todo) { if (todo.id == quot;quot; || !todo.id ) { return true } return false } private void fillSelectedTodoFromView() { selectedTodo().with { name = view.nameTextField?.text priority = view.priorityComboBox?.selectedItem selectedTodo().status = view.statusComboBox?.selectedItem completedDate = view.completedDateField?.date createdDate = view.createDateField?.date dueDate = view.dueDateField?.date note = view.noteTextField?.text } }
  • Service Save static void save(appContext, todo) { def userContext = appContext.userContext def put = new Put(url: APP_URL, userName: userContext.userName, password: userContext.password) put.queryString.add(quot;namequot;, todo.name) put.queryString.add(quot;priorityquot;, todo.priority) put.queryString.add(quot;statusquot;, todo.status) put.queryString.add(quot;notequot;, todo.note) put.queryString.add(quot;owner.idquot;, userContext.id) put.queryString.addDate(quot;createdDatequot;, todo.createdDate) def putResponse = put.text }
  • package http.utils class Put{ String url QueryString queryString = new QueryString() String content Put (HttpUtils) String contentType String text def userName def password String getText(){ def conn = new URL(url).openConnection() conn.setRequestMethod(quot;PUTquot; ) conn.setRequestProperty(quot;Content-Typequot; , contentType) conn.doOutput = true conn.doInput = true if (userName && password) { conn.setRequestProperty(quot;Authorizationquot;, quot;Basic ${userName}:${password}quot;) } conn.outputStream.withWriter { out -> out.write(queryString.toString()) out.flush() out.close() } def response if (conn.HTTP_OK == conn?.responseCode) { response = conn.content.text } else { response = quot;URL: quot; + this.toString() + quot;nquot; + quot;RESPONSE CODE: quot; + responseCode } conn.disconnect() return response } String toString(){ return url + quot;?quot; + queryString.toString() } }
  • RESTFul WebServices
  • class UserInfoController { def index = { redirect(action:show,params:params) } def show = { def result = session.user format(result) } def beforeInterceptor = { def authHeader = request.getHeader(quot;Authorizationquot;) if (authHeader) { def tokens = authHeader.split(' ') def user_password = tokens[1] tokens = user_password.split(':') def userid = tokens[0] def password = tokens[1] // At this point, the userid and password could be verified // to make sure that the person making the request is authenticated // // << AUTHENTICATION LOGIC / CALL >> // // Put look up the user object and put it into session for use // later by the controllers. def user = User.findByUserName(userid) if (user) { session.user = user } else { session.user = null } } } private format(obj) { def restType = (params.rest == quot;restquot;)?quot;XMLquot;:quot;JSONquot; println obj.quot;encodeAs$restTypequot;() render obj.quot;encodeAs$restTypequot;() } }
  • class UserInfoController { def index = { redirect(action:show,params:params) } def show = { def result = session.user format(result) } def beforeInterceptor = { def authHeader = request.getHeader(quot;Authorizationquot;) if (authHeader) { def tokens = authHeader.split(' ') def user_password = tokens[1] tokens = user_password.split(':') def userid = tokens[0] def password = tokens[1] // At this point, the userid and password could be verified // to make sure that the person making the request is authenticated // // << AUTHENTICATION LOGIC / CALL >> // // Put look up the user object and put it into session for use // later by the controllers. def user = User.findByUserName(userid) if (user) { session.user = user } else { session.user = null } } } private format(obj) { def restType = (params.rest == quot;restquot;)?quot;XMLquot;:quot;JSONquot; println obj.quot;encodeAs$restTypequot;() render obj.quot;encodeAs$restTypequot;() } }
  • Other Griffon Apps
  • http://github.com/jshingler/gcollabtodo/tree/master
  • Resources • Introduction to Groovy • Groovy Basics • More Advanced Groovy • Introduction to Grails • Building the User Interface • Building Domains and Services • Security in Grails • Web 2.0—Ajax and Friends • Web Services • Reporting • Batch Processing • Deploying and Upgrading • Alternative Clients
  • Resources • Griffon • griffon.codehause.org • griffon-user@groovy.codehause.org • Grails • www.grails.org Coming • Books Soon
  • Resources • SwingLabs • swinglabs.org • MigLayout • miglayout.org • GlazedLists • publicobject.com/glazedlists
  • Conclusion Thank You for your time • Blog: http://jshingler.blogspot.com • Email: ShinglerJim@gmail.com • LinkedIn: http://www.linkedin.com/in/jimshingler • Twitter: http://www.twitter.com/jshingler