Reference Manual for Gracelets - 2.0.0.RC2SourceForge.net Logo
1.2 - Introduction : Concepts
From the very beginning it is important to understand the page design concept behind gracelets. If this is not understood, it can cause some confusion in regards to expected functionality when writing gracelet pages.

This concept involves combined code that can participate in different parts of the JSF life cycle. This could be divided into three different aspects of a gracelet page:

Blueprint Code

In Facelets, when you design a view, you are really designing a blueprint. In other words you are saying, this is the blueprint or template, and I want facelets to make a cookie-cutter copy of this blueprint that will result in a JSF view. Obviously since Gracelets is an extension to Facelets, this same logic applies. A major part of every Gracelet view is blueprint code. This code is only ran once when the page is initially compiled and ran only again when the gracelet source code has been changed.

This is very efficient, since the actual view is compiled into a singleton in memory and the JSF cookie cutter copies can be made very quickly. Thus when writing a gracelet view, you must have in mind that the blueprint code is only ran ONCE and is used to create the blueprint off of which each view will be created. A JSF view is made off the blueprint each time there is a new request, subsequent requests where the user sends information or requests some action to be done reuse the JSF view previously made.

Render Code

In Gracelets you can write component libraries and also use inline render time components in your gracelet views. The render code used in these components is ran every time the page is rendered. This code normally uses normal markup builders than make xml markup easier to write.

Thus, in these sections of a gracelet view or component library you must have clearly in mind that your are writing render time code, code that is not ran only once like the blueprint code, but rather every time the view is rendered.

Action Code

In Gracelets you can completely avoid using EL (Expression Language) strings, using closures instead of action expressions, value closures instead of value expressions and so forth. This code is ran depending on its context. Value closures are ran every time the value is requested, this could be at render time or at any other part of the JSF life cycle. Action closures will be ran when their corresponding action components fire an event, like when the user clicks on a button.

Example

Below is an example gracelet view that contains each possible aspect of a view mentioned above. Each distinct section will be highlighted so was to make clear when the code is ran.

Toggle Line Numbers
1 import groovy.util.XmlParser 
2  
3 Factory("currentUser") {  
4     [loggedIn: false]  
5 } 
6  
7 xh.html { 
8      
9     head { title("Concept Example") } 
10      
11     body { 
12          
13         div(class: "menu") { 
14             render { cmp -> 
15                 def x = cmp.builder 
16                 def menu = new XmlParser().parse(parentPath."menu.xml".absoluteFile) 
17                 menu.item.each { item -> 
18                     x.a(href: item.@href) { print item.@label } 
19                 } 
20             } 
21         } 
22          
23         div(class: "content") { 
24             h.form(rendered: {  
25                 !currentUser.loggedIn 
26             }) { 
27                 print "Username: ";  
28                 h.inputText(value: Value({  
29                     currentUser.username  
30                 }));  
31                 xh.br(); 
32                  
33                 print "Password: ";  
34                 h.inputText(value: Value({  
35                     currentUser.password  
36                 }));  
37                 xh.br(); 
38                  
39                 h.commandButton("Login", action: { 
40                     def user = myDB.getResults("SELECT u FROM User u WHERE u.username = :u",u: currentUser.username) 
41                     if (user != null && user.password == currentUser.password) { 
42                         currentUser.loggedIn = true 
43                     } 
44                 }) 
45             } 
46  
47             h.outputText(rendered: {  
48                 currentUser.loggedIn 
49             }) { 
50                 u.insert() 
51             } 
52         } 
53          
54     } 
55      
56 } 
The code in blue is blueprint code. This code is only ran once in order to build the blueprint that will be used to create this view.

The code in green is render code. This code will be ran each time the page is rendered. In this instance the code reads from an xml file that is in the same directory as the view so as to get a list of items for the menu.

The code in red is action code. On line 4, this is code inside of a factory closure, which will initiate the currentUser bean when it is null. On line 25, this is part of a value closure, which will determine in this case the rendered logic for the form, which here says that if the loggedIn flag is false, show the login form. On line 29 and 35 we have a value binding closures which allows the value of the specified bean property in the closure to be used as the binding for the input components. On lines 40-43 we have action closure code, which will be executed when the user clicks on the "Login" button. And lastly on line 48 we have another value closure which is also determining whether or not this template will show the actual view using it depending on the loggedIn value of the currentUser bean.