Professional Documents
Culture Documents
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?
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.
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.
Griffons 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
@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
Status Bar
About Box
Tips
Login Dialog
Status Bar
About Box
Tips
Login Dialog
Status Bar
About Box
Tips
Login Dialog
Status Bar
About Box
Tips
Login Dialog
Status Bar
About Box
Tips
Login Dialog
Status Bar
About Box
Tips
Login Dialog
Status Bar
About Box
Tips
Login Dialog
Status Bar
About Box
Tips
Login Dialog
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
Put
Post Griffon Framework
Delete
Organization
Menu Bar
Controller View
About Dialog
Content Pane
Model
Tool Bar
Services
Status Bar
Http Utils
Get
Put
Post Griffon Framework
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("Loading Data")
busy
model.todos.clear()
model.todos.addAll (TodoService.list(appContext))
norm
setStatus("Finished Loading Data")
}
class TodoService {
static String APP_URL = 'http://localhost:8080/collab-todo/json/todo'
def todo
def outputList = []
jsonarray.each {
todo = JsonUtil.jsonToObject(it.toString(), Todo.class)
outputList.add todo
}
return outputList
}
Lets 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 = "GET"
conn.doOutput = true
def content
if (conn.responseCode == conn.HTTP_OK) {
response = conn.content.text
} else {
response = "URL: " + this.toString() + "\n" +
"RESPONSE CODE: " + conn.responseCode
throw new ResourceException(response)
}
conn.disconnect()
return response
} catch (Exception e) {
println "Caught Exception ${e}"
throw new ResourceException(e)
}
}
String toString(){
return url + "?" + queryString.toString()
}
void saveTodo(event) {
fillSelectedTodoFromView()
put.queryString.add("name", todo.name)
put.queryString.add("priority", todo.priority)
put.queryString.add("status", todo.status)
put.queryString.add("note", todo.note)
put.queryString.add("owner.id", userContext.id)
put.queryString.addDate("createdDate", todo.createdDate)
Put (HttpUtils)
String contentType
String text
def userName
def password
String getText(){
def conn = new URL(url).openConnection()
conn.setRequestMethod("PUT" )
conn.setRequestProperty("Content-Type" , contentType)
conn.doOutput = true
conn.doInput = true
def response
if (conn.HTTP_OK == conn?.responseCode) {
response = conn.content.text
} else {
response = "URL: " + this.toString() + "\n" +
"RESPONSE CODE: " + responseCode
}
conn.disconnect()
return response
}
String toString(){
return url + "?" + queryString.toString()
}
}
RESTFul WebServices
class UserInfoController {
def index = { redirect(action:show,params:params) }
def show = {
def result = session.user
format(result)
}
def beforeInterceptor = {
private format(obj) {
def restType = (params.rest == "rest")?"XML":"JSON"
println obj."encodeAs$restType"()
render obj."encodeAs$restType"()
}
}
class UserInfoController {
def index = { redirect(action:show,params:params) }
def show = {
def result = session.user
format(result)
}
def beforeInterceptor = {
private format(obj) {
def restType = (params.rest == "rest")?"XML":"JSON"
println obj."encodeAs$restType"()
render obj."encodeAs$restType"()
}
}
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.0Ajax 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