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