Reference Manual for Gracelets - 2.0.0.RC2SourceForge.net Logo
3.3 - Examples : User Manager
This example will assume the use of the JPA extension (discussed in the Integration section).

Lets say you have an entity called User, it could be defined and compiled in Java or Groovy:

User Entity in Java
Toggle Line Numbers
1 package org.ponder.gracelets.demo.userman; 
2  
3 import javax.persistence.Entity; 
4 import javax.persistence.GeneratedValue; 
5 import javax.persistence.Id; 
6  
7 @Entity public class User { 
8      
9     int id; 
10      
11     String name; 
12     String username; 
13     String password; 
14      
15     @Id @GeneratedValue public int getId() { 
16         return id; 
17     } 
18     public void setId(int id) { 
19         this.id = id; 
20     } 
21     public String getName() { 
22         return name; 
23     } 
24     public void setName(String name) { 
25         this.name = name; 
26     } 
27     public String getUsername() { 
28         return username; 
29     } 
30     public void setUsername(String username) { 
31         this.username = username; 
32     } 
33     public String getPassword() { 
34         return password; 
35     } 
36     public void setPassword(String password) { 
37         this.password = password; 
38     } 
39  
40 } 
You would put your entity (or entities) in your WEB-INF/classes folder along with your persistence.properties setup (if using the Gracelets JPA extension). We will assume the default persistence session name of 'storage'.

Next you could setup your controller (in the WEB-INF/gracelet/controller directory):

User Controller
Toggle Line Numbers
1 import org.ponder.gracelets.demo.userman.User 
2  
3 class UserManager { 
4      
5     static def name = "userman" 
6     static def scope = "conversation" 
7      
8     static void initialize (binding) { 
9         binding.DataModel("usermanUsers") {  
10             def model = demodb.managedQuery("u", "User u", "", "").model 
11             model.whereCriteria.putAll(  
12                 [name: "UPPER(u.name) LIKE UPPER(:name)", username: "UPPER(u.username) LIKE UPPER(:username)"] 
13             ); 
14             return model 
15         } 
16     } 
17      
18     def subPage = "list" 
19      
20     def nameField = "u.name" 
21     def usernameField = "u.username" 
22      
23     def getCriteria () { usermanUsers.criteria } 
24      
25     void newUser () { selectedUser = new User(); subPage = "edit" } 
26     void editUser (user) { selectedUser = user; subPage = "edit" } 
27      
28     void remove (user) { demodb.remove(user); usermanUsers.clear() } 
29      
30     void userList () { subPage = "list" } 
31      
32     void save () { save(selectedUser); } 
33     void save (user) { demodb.save(user); usermanUsers.clear(); subPage = "list" } 
34      
35     void search () { usermanUsers.applyCriteria() } 
36      
37 } 
Above you may wonder about some of the facilities, like a query object (lines #19 and #23) off the data model. That is specific to the JPA wrapper that is returned when using managed queries (line #12). Of course, all this comes with gracelets.

You would then make your view to manage the users, a simple CRUD view:

User Manager View
Toggle Line Numbers
1 xh.html { 
2      
3     head {  
4         title("User Manager") 
5          
6         link(rel: "stylesheet", href: "style/userman.css", type: "text/css") 
7     } 
8      
9     body { 
10          
11         h.messages() 
12          
13         g.subpages(value: Value { userman.subPage }) { 
14              
15             u.component(page: "list") { 
16                  
17                 g.form(id: "filter") { 
18                     xh.fieldset { 
19                         legend("User Search") 
20                         table(width: "100%") { 
21                             tr { td ("Name:"); td {  
22                                 h.inputText(value: Value { userman.criteria.name }, converter: Converter(  
23                                     toString: { val -> val.replaceAll("%","") }, toValue: { val -> "%$val%" } 
24                                 ))  
25                             } } 
26                             tr { td ("Username:"); td {  
27                                 h.inputText(value: Value { userman.criteria.username }, converter: Converter(  
28                                     toString: { val -> val.replaceAll("%","") }, toValue: { val -> "%$val%" } 
29                                 ))  
30                             } } 
31                              
32                             tr { 
33                                 td (colspan: 2, align: "right", class: "button_bar") { 
34                                     h.commandButton("New user...", immediate: true, action: { userman.newUser() }) 
35                                     h.commandButton("Search", action: { userman.search() }) 
36                                 } 
37                             } 
38                         } 
39                     } 
40                 } 
41                  
42                 g.form(id: "grid") { 
43                     g.grid(caption: "User List", value: { usermanUsers }, width: "100%", var: "user") { 
44                          
45                         h.column(facets: [header: { print "Name" }], sortable: { userman.nameField }) { 
46                             print { user.name } 
47                         } 
48                         h.column(facets: [header: { print "Username" }], sortable: { userman.usernameField }) { 
49                             print { user.username } 
50                         } 
51                          
52                         h.column(facets: [header: { div("Options", style: "text-align: right") }]) { 
53                             div (style: "text-align: right") { 
54                                 h.commandLink("[ Edit ]", action: { userman.editUser(user) }) 
55                                 h.commandLink("[ Remove ]", action: {  
56                                     userman.remove(user);  
57                                     jsfMessages.add("User has been removed: $user.name")  
58                                 }, onclick: "if (!confirm('Are you sure?')) { return false; }") 
59                             } 
60                         } 
61                          
62                     } 
63                 } 
64                  
65             } 
66              
67             u.component(page: "edit") { 
68              
69                 g.form(id: "edit") { 
70                      
71                     xh.fieldset { 
72                         legend("User Edit") 
73                         table(width: "100%") { 
74                             tr { td("Name: "); td { h.inputText(required: true, value: Value { selectedUser.name }) } } 
75                             tr { td("Username: "); td { h.inputText(required: true, value: Value { selectedUser.username }) } } 
76                             tr { td("Password: "); td {  
77                                 h.inputSecret(required: { selectedUser.id == 0 }, valueChangeListener: { evt ->  
78                                     if (evt.newValue) { 
79                                         selectedUser.password = evt.newValue 
80                                         if (selectedUser.id) jsfMessages.add("Password for $selectedUser.name has been set") 
81                                     } 
82                                 })  
83                             } } 
84                              
85                             tr { td (align: "right", colspan: 2, class: "button_bar") { 
86                                 h.commandButton("Cancel", immediate: true, action: { userman.userList() }) 
87                                 h.commandButton("Save Changes", action: { 
88                                     userman.save(); 
89                                     jsfMessages.add("User changes saved") 
90                                 }) 
91                             } } 
92                         } 
93                     } 
94                      
95                 } 
96                  
97             } 
98              
99         } 
100          
101     } 
102      
103 }