Wednesday, July 14, 2010

Apache Click 2.2.0: DataProvider

In this three part series I'll blog about some of the new features added in 2.2.0, namely:

  1. DataProviders (Japanese version)
  2. Explicit binding (Japanese version)
  3. Dynamic Form Validation ( Japanese version)
    In this first installment I'll cover DataProviders and how they simplify Click Page implementations.

    To understand the benefits of DataProviders, we need to look at the problem they are trying to solve. To start off with let's do a quick recap of the major life cycle events of a Click Page. Below we list the events in the order they are executed:
    • <<init>>: page is created
    • onInit: page controls are created and added to the page
    • onProcess: control values are bound to request parameters, control values are validated and action listeners are fired
    • onRender: database intensive operations are performed here
    Click allows certain events to be skipped depending on the outcome of a previous event. onRender for example, will be skipped if a Control action returns false. This together with the fact that onRender is the last event exposed by Click makes onRender ideal for database intensive operations. If a control action listener decides to redirect to a different page, it can return false to bypass the slow onRender method.

    For example:
    public class CustomerPage extends BorderPage {
    
        private Table table = new Table("table");
        private ActionLink editLink = new EditLink("edit");
    
        @Override
        public void onInit() {
            super.onInit();
    
            table.add(new Column("firstname"));
    
            ...
    
            editLink.setActionListener(new ActionListener() {
                public boolean onAction(Control source) {
                    Map params = Collections.singletonMap("id", editLink.getValue());
    
                   // Redirect to edit customer page and pass the selected customer ID
                   setRedirect(EditCustomerPage.class, params);
                   return false;
                }
            });
        }
    
        @Override
        public void onRender() {
            // Database intensive operation: retrieving all customers from the database
            List<Customer> customers = getCustomerService.getCustomers();
            table.setRows(customers);
        }
    }
    
    In the example above you can see that we don't want to hit the database and retrieve all the customers only to be redirected to another page that does not render the customers we retrieved. In other words, because the customers won't be rendered by the page we redirect to, we don't want to pay for the database hit. Since the onRender event is skipped if an action listener returns false, it makes sense to place database intensive code there.

    Inconsistent

    Unfortunately this pattern cannot be applied to all controls. Some controls need their values populated before the onProcess event, either for validation or parameter binding purposes. For example, the Select control validation depends on its values to determines whether or not a valid selection was made. FormTable needs to have it's rows set  in order to update its entity values against incoming request parameters.

    Having some of the controls populated in onInit and others in onRender is inconsistent and a common pitfall for new users as they have to figure out which controls should be populated in which event.

    DataProvider

    The solution used in Click was to add a DataProvider interface to enable on demand data loading. A DataProvider has a single method, "public List getData()", that the control can invoke when it needs it's data. For example, a Table will invoke getData when it is rendered, a Select will invoke getData when it is validated and a FormTable will invoke getData when it is processed.

    DataProviders leads to a more consistent Page implementation where all control creation logic can be encapsulated in the onInit event or even the page constructor. For example:

    public class CustomerPage extends BorderPage {
    
        private Table table = new Table("table");
        private Select select = new Select("markets");
    
        @Override
        public void onInit() {
            super.onInit();
    
            table.add(new Column("firstname"));
    
            ...
    
            table.setDataProvider(new DataProvider() {
                public List<Customer> getData() {
                    return getCustomerService().getCustomers();
                }
            });
    
            select.setDataProvider(new DataProvider() {
                public List<Option> getData() {
                    List options = new ArrayList();
                    for (Market market : getMarketService().getMarkets()) {
                        options.add(new Option(market.getId(), market.getName());
                    }
                    return options;
                }
            });
        }
    }
    
    In the example above we use DataProviders for both the Table and Select control. The Table data is only retrieved when the Table is rendered, so in the event of a redirect, the database operation is skipped. The Page is now consistent as all control setup logic is placed inside the onInit event.

    Is onRender still necessary?

    Absolutely. While DataProviders allow control creation logic to be encapsulated within the onInit event, not all data needs to be represented with controls. The Page template (Velocity) for example can be used to render markup for the customers passed from the page. onRender could still be used to retrieve the customers and make it available to the template. For example:

    public class CustomerPage extends BorderPage {
    
        public void onRender() {
            addModel("customers", getCustomerService().getCustomers());
        }
    } 

    <table>
    ...
    
    #foreach($customer in $customers)
      <tr>
        <td>
          $customer.name
        <td>
        <td>
          $customer.holdings
        <td>
      </tr>
    #end
    </table> 

    If an action listener returns false, onRender is skipped and the database operation won't be performed, which is exactly the behavior we want.

    Hope this overview was helpful. In the next installment I'll cover Explicit binding and Dynamic Form Validation, which both simplifies dynamic form creation.

    Saturday, May 15, 2010

    Apache Click v2.2.0 has been released

    Click 2.2.0 final is available for download. Major new features include DataProviders for on-demand data loading and a Page interceptor facility for implementing cross cutting concerns such as security and transaction handling. There are also improved support for dynamic forms and stateful pages.

    New features and improvements:
    • Added DataProvider support for Table, Select, PickList and CheckList providing on demand loading of data. With DataProviders, users won't have to be concerned about which page event (onInit or onRender) to set the data on the control [CLK-640].
    • Added PagingDataProvider interface to support large paginated result sets for Tables [CLK-640].
    • Added a MenuFactory for creating and loading Menus from configuration files. All the static Menu methods have been deprecated and will be removed in a future release.
    • Added an option for MenuFactory to not statically cache menus. This allows developers to cache menus in different scopes such as HttpSession. [CLK-405].
    • Added i18n support for Menus loaded from menu.xml. The menu DTD now includes a new name attribute. By specifying a name attribute in menu.xml, the Menu will attempt to load its label and title from resource bundles [CLK-591].
    • Added a Page Interceptor facility that provides an extension point for code which can listen to key page events and also interrupt normal page processing flow. [CLK-598].
    • Added improved dynamic Form support. Forms can now optionally bypass validation for JavaScript based submissions using the new JavaScript function "Click.submit(formName, validate)" [CLK-638].
    • Added improved dynamic Page and Form behaviour through new helper methods that can bind and validate Forms and Fields before the onProcess page event e.g. in the Page constructor or "onInit" event. The new methods are:
    • Added improved disabled behavior through the following changes:
      • Disabled fields are not processed or validated
      • Disabled field values are not copied to domain objects
      • Disabled fields are automatically enabled if the field has an incoming request parameter, indicating that the field was enabled on the client using JavaScript. Please note that this behavior does not apply to Checkbox or Radio fields. See the setDisabled() javadoc for details [CLK-646].
    • Added new method Container.replace for replacing an existing control with a new control. In previous releases, an exception would be raised if a page or container already contained a control with the same name as the newly added control. In 2.2.0 the replace method is automatically called when adding a control which name matches that of an existing control in the page or container. This behavior will likely only benefit stateful pages since stateless pages are recreated each request [CLK-666].
    • Added methods to Fields for styling their labels. See new methods Field.setLabelStyle(String) and Field.setLabelStyleClass(String). This issue was raised by Stefax [CLK-595].
    • Added methods to Fields for providing styling hints to their containing elements. See new methods Field.setParentStyleHint(String) and Field.setParentStyleClassHint(String). This issue was raised by Stefax [CLK-595].
    • Added trim property to Field for controlling if the Field request parameter is trimmed or not. See new method Field.setTrim(boolean). This issue was raised by Andrey Rybin [CLK-627].
    • Added new Context methods Context.hasRequestParameter(String) and Context.hasRequestAttribute(String).
    • Added support to Select for a default option that can be used to validate non selection against and allows the Select to only populate its optionList at rendering time, instead of during onProcess event. [CLK-641].
    • Improved default autobinding mode to bind both public fields and fields annotated with @Bindable. In previous versions the default autobinding mode only binded public Page fields [CLK-648].
    • Added mock support for user principals and roles. This issue was raised and fixed by Sven Pfeiffer [CLK-585].
    • Added localized Date format pattern support. This issue was raised by Andrey Rybin [CLK-610].
    • Added Polish resource bundle for DateField. This issue was raised and fixed by Rafal Rusin [CLK-624].
    • Migrated controls to import resources through Elements and the getHeadElements method [CLK-647].
    • Improved SpringClickServlet to re-inject transient beans after stateful page deserialization. This feature is only supported when the stateful page instance is created by Click, not Spring [CLK-667].
    • Replaced Page and Control getMessage methods with varargs equivalents [CLK-604].
    • Removed Click core's dependency on Velocity. This issue was raised by by Andrey Rybin [CLK-606].
    • Replaced multiple ClickUtils close methods with a single method accepting a Closeable. This issue was raised by Andrey Rybin [CLK-620].
    • Improved ClickServlet to use the response's OutputStream if the Writer cannot be retrieved [CLK-644].
    • Fixed issue where RadioGroup label referenced a non-existing ID. RadioGroup is now wrapped inside a span tag with the given ID. This issue was raised and fixed by Finn Bock [CLK-577].
    • Fixed DateField to set seconds back to zero. This issue was raised by Andrey Rybin [CLK-664].
    • The menu.dtd has been published to http://click.apache.org/dtds/menu-2.2.dtd. If you want your configuration to conform to the menu.dtd, include the following declaration in your menu.xml:
      <!DOCTYPE menu PUBLIC
      "-//Apache Software Foundation//DTD Click Menu 2.2//EN"
      "http://click.apache.org/dtds/menu-2.2.dtd">
      
    • The new click-2.2.dtd has been published to http://click.apache.org/dtds/click-2.2.dtd. If you want your configuration to conform to the click.dtd, include the following declaration in your click.xml:
      <!DOCTYPE click-app PUBLIC
      "-//Apache Software Foundation//DTD Click Configuration 2.2//EN"
      "http://click.apache.org/dtds/click-2.2.dtd">
      
    New examples:
    • Dynamic Form demonstrates how to dynamically add new Fields at runtime.
    • Dynamic FieldSet demonstrates how to dynamically add a FieldSet at runtime.
    • Dynamic Select demonstrates how to dynamically add fields based on a Select field value.
    • Disabled Demo demonstrates the behavior of disabled fields.
    Enjoy.

    - The Click team

    Saturday, May 1, 2010

    Apache Click v2.2.0-RC1 now available

    Click 2.2.0-RC1 is now available. Major new features include DataProviders for on-demand data loading and a Page interceptor facility for implementing cross cutting concerns such as security and transaction handling. There are also improved support for dynamic forms and stateful pages.

    New features and improvements:
    • Added DataProvider support for Table, Select, PickList and CheckList providing on demand loading of data. With DataProviders, users won't have to be concerned about which page event (onInit or onRender) to set the data on the control [CLK-640].
    • Added PagingDataProvider interface to support large paginated result sets for Tables [CLK-640].
    • Added a MenuFactory for creating and loading Menus from configuration files. All the static Menu methods have been deprecated and will be removed in a future release.
    • Added an option for MenuFactory to not statically cache menus. This allows developers to cache menus in different scopes such as HttpSession. [CLK-405].
    • Added i18n support for Menus loaded from menu.xml. The menu DTD now includes a new name attribute. By specifying a name attribute in menu.xml, the Menu will attempt to load its label and title from resource bundles [CLK-591].
    • Added a Page Interceptor facility that provides an extension point for code which can listen to key page events and also interrupt normal page processing flow. [CLK-598].
    • Added improved dynamic Form support. Forms can now optionally bypass validation for JavaScript based submissions using the new JavaScript function "Click.submit(formName, validate)" [CLK-638].
    • Added improved dynamic Page and Form behaviour through new helper methods that can bind and validate Forms and Fields before the onProcess page event e.g. in the Page constructor or "onInit" event. The new methods are:
    • Added improved disabled behavior through the following changes:
      • Disabled fields are not processed or validated
      • Disabled field values are not copied to domain objects
      • Disabled fields are automatically enabled if the field has an incoming request parameter, indicating that the field was enabled on the client using JavaScript. Please note that this behavior does not apply to Checkbox or Radio fields. See the setDisabled() javadoc for details [CLK-646].
    • Added new method Container.replace for replacing an existing control with a new control. In previous releases, an exception would be raised if a page or container already contained a control with the same name as the newly added control. In 2.2.0 the replace method is automatically called when adding a control which name matches that of an existing control in the page or container. This behavior will likely only benefit stateful pages since stateless pages are recreated each request [CLK-666].
    • Added methods to Fields for styling their labels. See new methods Field.setLabelStyle(String) and Field.setLabelStyleClass(String). This issue was raised by Stefax [CLK-595].
    • Added methods to Fields for providing styling hints to their containing elements. See new methods Field.setParentStyleHint(String) and Field.setParentStyleClassHint(String). This issue was raised by Stefax [CLK-595].
    • Added trim property to Field for controlling if the Field request parameter is trimmed or not. See new method Field.setTrim(boolean). This issue was raised by Andrey Rybin [CLK-627].
    • Added new Context methods Context.hasRequestParameter(String) and Context.hasRequestAttribute(String).
    • Added support to Select for a default option that can be used to validate non selection against and allows the Select to only populate its optionList at rendering time, instead of during onProcess event. [CLK-641].
    • Improved default autobinding mode to bind both public fields and fields annotated with @Bindable. In previous versions the default autobinding mode only binded public Page fields [CLK-648].
    • Added mock support for user principals and roles. This issue was raised and fixed by Sven Pfeiffer [CLK-585].
    • Added localized Date format pattern support. This issue was raised by Andrey Rybin [CLK-610].
    • Added Polish resource bundle for DateField. This issue was raised and fixed by Rafal Rusin [CLK-624].
    • Migrated controls to import resources through Elements and the getHeadElements method [CLK-647].
    • Improved SpringClickServlet to re-inject transient beans after stateful page deserialization. This feature is only supported when the stateful page instance is created by Click, not Spring [CLK-667].
    • Replaced Page and Control getMessage methods with varargs equivalents [CLK-604].
    • Removed Click core's dependency on Velocity. This issue was raised by by Andrey Rybin [CLK-606].
    • Replaced multiple ClickUtils close methods with a single method accepting a Closeable. This issue was raised by Andrey Rybin [CLK-620].
    • Improved ClickServlet to use the response's OutputStream if the Writer cannot be retrieved [CLK-644].
    • Fixed issue where RadioGroup label referenced a non-existing ID. RadioGroup is now wrapped inside a span tag with the given ID. This issue was raised and fixed by Finn Bock [CLK-577].
    • Fixed DateField to set seconds back to zero. This issue was raised by Andrey Rybin [CLK-664].
    • The menu.dtd has been published to http://click.apache.org/dtds/menu-2.2.dtd. If you want your configuration to conform to the menu.dtd, include the following declaration in your menu.xml:
      <!DOCTYPE menu PUBLIC
      "-//Apache Software Foundation//DTD Click Menu 2.2//EN"
      "http://click.apache.org/dtds/menu-2.2.dtd">
      
    • The new click-2.2.dtd has been published to http://click.apache.org/dtds/click-2.2.dtd. If you want your configuration to conform to the click.dtd, include the following declaration in your click.xml:
      <!DOCTYPE click-app PUBLIC
      "-//Apache Software Foundation//DTD Click Configuration 2.2//EN"
      "http://click.apache.org/dtds/click-2.2.dtd">
      
    New examples:
    • Dynamic Form demonstrates how to dynamically add new Fields at runtime.
    • Dynamic FieldSet demonstrates how to dynamically add a FieldSet at runtime.
    • Dynamic Select demonstrates how to dynamically add fields based on a Select field value.
    • Disabled Demo demonstrates the behavior of disabled fields.
    Enjoy.

    - The Click team

    Friday, February 19, 2010

    ClickIDE 2.1.0.0 released: support Apache Click 2.1.0 and Eclipse 3.5

    The latest version of ClickIDE is available. This release supports Click 2.1.0 and Eclipse 3.5.

    ClickIDE is based on Eclipse and the Eclipse Web Tools Project (WTP), and provides extended features for developing web applications using Click.

    Important links:

    Main features:

    • Fast switching between Page classes and templates (Ctrl+Alt+S)
    • Project creation wizard
    • Click page creation wizard
    • Visual editor for the Click configuration file
    • Velocity template editor
    • Spring Framework and Apache Cayenne Integration
    • Integrated Click documentation
    New features and enhancements in 2.1.0.0:
    • Upgraded to Cayenne to 3.0 M6.
    • Added "Use PerformanceFilter" option in the project creation wizard.
    • Added switching comment action in the Velocity editor ([CTRL] + [/]).
    • Added (*) to required attributes in the click.xml editor.

    Enjoy Click!

    Friday, February 5, 2010

    Apache Click becomes a Top-Level Project and v2.1.0 now available

    Apache Click has become a new Apache Top Level Project (TLP), signifying that Click is a well-governed project under the Apache Software Foundation principles.

    Furthermore Click 2.1.0 has been released sporting many new features, including support for Google App Engine, a free Java hosting environment from Google.

    New features and improvements:
    • Added support for Google App Engine, a free Java hosting environment from Google. This provides an ideal environment for students and startups to easily host their Click applications online. See GoogleAppEngineListener for details [560].
    • Added support for an in-memory File Upload Service that can be used for uploading files in a Google App Engine environment.
    • Added support for templates with custom extensions through the new ConfigService.isTemplate method. The default ConfigService implementation, XmlConfigService, provides support for the extensions .htm and .jsp, but new extensions can be provided in a subclass. See the JavaDoc for details [568].
    • Added support to the Page class for conditionally including Control head elements through the new method includeControlHeadElements [571].
    • Added support to deploy resources inside JARs from the Servlet 3.0 compliant location, META-INF/resources. Click's own pre-packaged resources are now also located in the JAR under META-INF/resources [570].
    • Added new Calendar popup to DateField. This Calendar popup uses Calendar Date Select which is based on the Prototype JavaScript library.

      Please note if you don't want a dependency on the Prototype library you can use the third-party Click Calendar instead.

    • Added first class support for HEAD elements such as JavaScript and Css. The following classes were added: Element, ResourceElement, JsImport, JsScript, CssImport and CssStyle. A new method was added to Page and Control: Control.getHeadElements() and Page.getHeadElements() [501].
    • Added SubmitLink control that can submit a Form [519].
    • Added HiddenList control for rendering and submitting a list of hidden fields [491].
    • Added pluggable security access controller (AccessController) to Menu class. This pluggable interface enable use of security frameworks such as Spring Security (Acegi) or JSecurity to control user access to Menu items. This issue was raised by Demetrios Kyriakis [406].
    • Added an Ant task, called DeployTask, for deploying static resources at build time. This task is useful when deploying Click applications in restricted environments. For more details see the section: deploying resources in a restricted environment.
    • Added a ResourceService, for serving static resources at runtime. This service is useful when deploying Click applications in restricted environments. For more details see the section: deploying resources in a restricted environment [564].
    • Added method, ClickUtils.createTemplateModel, which returns a template model containing objects such as the Context path, Page path, HTTP request, HTTP response, HTTP session etc.
    • Added ability to specify a custom TreeNode icon through the new method TreeNode.setIcon(String). This issue was raised and fixed by Tim Hooper [494].
    • Added method Format.url for encoding URL's in templates [399].
    • Added method FieldColumn.setProperty that can be overriden to provide custom binding for complex domain objects. This issue was raised and fixed by WarnerJan Veldhuis [528].
    • Added TypeConverter configuration option to ClickServlet. See getTypeConverter() method for details. This issue was raised Joseph Schmidt and fixed by Adrian A. [539].
    • Added Slf4jLogService for supporting multiple application servers. This issue was raised Oliver Burn [555].
    • Added @Bindable annotation support for page field autobinding. @Bindable supports public, protected and private Page variables [556, 599 ].
    • Added property files with translation for the Russian language. This issue was raised and fixed by Andrey Rybin [607], [611].
    • Added new Tree methods setWidth / getWidth and setHeight / getHeight. Also fixed rendering issues in IE6/7 for long node labels that overflow the tree width [616].
    • The click.dtd has been published to http://click.apache.org/dtds/click-2.1.dtd.
    • If you want your configuration to conform to the click.dtd, include the following declaration in your click.xml:
      <!DOCTYPE click-app PUBLIC
      "-//Apache Software Foundation//DTD Click Configuration 2.1//EN"
      "http://click.apache.org/dtds/click_2_1.dtd">
    • Improved Form validation to allow Form subclasses to override the validate method and implement cross-field validation. The following changes were made: the previous validate method was renamed to validateFileUpload and a new empty validate method was introduced, that can safely be overridden in subclasses [572].
    • Improved Page redirect to support parameters. See the new Page methods setRedirect(String, Map) and setRedirect(Class, Map) This issue was raised and fixed by Adrian [536].
    • Improved Link Controls to support multivalued parameters through the new AbstractLink methods getParameterValues() and setParameterValues() [554].
    • Improved Table to support very large datasets by promoting the methods getFirstRow() and getLastRow() as public. These methods provide the necessary information to only retrieve the displayed rows [504].
    • Improved LinkDecorator to support target identfier property parameter names. This issue was raised by Demetrios Kyriakis and fixed by fixed by Adrian A. [400].
    • Improved PickList methods getValueObject() and setValueObject(Object) to delegate to getSelectedValues() and addSelectedValue(String) respectively [490].
    • Improved Spring integration with SpringClickServlet and PageScopeResolver, supporting Spring instantiated Pages with @Component configuration [534].
    • Improved CompressionServletResponseWrapper and CompressionResponseStream classes to have public visibility to enable use in custom servlet Filters [547].
    • Improved Menu control to render attribute class="selected" when the menu item is selected. This issue was raised and fixed by Frederic Daoud [551].
    • Improved PerformanceFilter to implement exclude-paths filtering [498].
    • Improved XmlConfigService to scan for deployable resources inside folders on the classpath [552].
    • Improved Cayenne DataContextFilter, including adding support for LifecycleListener registration [559].
    • Improved AbstractLink to allow rendering of both icon and label in Link controls (default behavior renders either a label or an icon) [535].
    • Improved Page and Control message handling with null args. This issue was raised by WarnerJan Veldhuis [600].
    • Fixed resource deployment on JBoss 5 and up. The solution is based on the work done by the Stripes Framework developers [589].

    Deprecated:

    Updated third-party libraries:
    • Update Velocity library to version 1.6.3.
    • Update Cayenne library to version 3.0M6.
    • Update Prototype.js library to version 1.6.1.

    New Documentation:

    New examples:

    Enjoy.

    - The Click team

    Tuesday, January 5, 2010

    New book: Getting Started With Apache Click

    We start 2010 with some great news. Freddy Daoud just announced his new book: Getting started with Apache Click. Finally, a book is available on the Click framework that provides a great way for getting started quickly.

    From the website:

    This book will help you get started with this excellent framework, starting with the basics and moving on to creating a sample application. You'll also learn how to integrate popular third-party frameworks such as Spring, Hibernate, Java Persistence API (JPA), and more.
    There is also a chapter on authentication and authorization which integrates Click and Apache Shiro, an open source security framework also hosted at Apache.

    You can view the book table of contents here, and download the example source code here.

    Enjoy.

    The Click team.

    Saturday, October 24, 2009

    Netbeans plugin released for Apache Click

    Hantsy Bai has announced the release of a Netbeans plugin for Apache Click. Netbeans users can now enjoy the same features provided by ClickIDE, the Eclipse based plugin.

    Please note the plugin targets Netbeans 6.7.1 and might not work with earlier versions.

    Features of the plugin includes:

    • Wizard for creating a new Click project
    • Wizard for creating new pages and templates
    • Quickly switch between a Page class, template and property (you can also define keyboard shortcuts for these functions)
    • Provides basic code completion, error checking, hyperlinking and refactoring for click.xml and menu.xml

    Not sure if its a feature of the plugin or of Netbeans itself, but the plugin automatically recognized my existing Click projects which is a nice touch.

    Here are some screenshots of the plugin in action.


    • Create a new Click project:


    • Create a new Click page and template:


    • Switch to the Page template:


    • Switch to the Page class:


    • Define keyboard shortcuts for the "Go to Page Class", "Go to Page Template" and "Go to Page Properties" functions: