Previous Section  < Day Day Up >  Next Section

2.3 Developing Components and Integration Code

The component writer develops all application-specific Java code needed for the user interface, ranging from simple classes that tie the user interface to the application backend code developed by the application developer to custom user interface components when the ones provided by JSF aren't sufficient.

Figure 2-2 shows the main classes and interfaces used by the newsletter application.

Figure 2-2. JSF component-related classes and the Subscriber application class
figs/Jsf_0202.gif

You probably recognize the Subscriber class from the previous section. The component writer develops the SubscriberHandler class, as shown in this section. All the other classes in Figure 2-2 are provided by the JSF implementation.

The UIComponentBase class is the base class for all JSF UI components. Subclasses represent specific interface elements, such as text fields, links and buttons, labels, menus and selection lists. JSF includes a set of component classes that can be used right out of the box, such as the ones shown in Figure 2-2, but a component writer can also implement custom components if needed. The UIInput class represents an input field and lets you bind the component to an application model through a value binding. When a component is rendered, it pulls its value from the application model object based on this value binding. Similarly, when an input component processes a request, it updates the model it's bound to with the value received with the request. In this example, value bindings for the UIInput and the UISelectMany (the checkbox group) components bind the components to the corresponding properties in the Subscriber application class.

The components fire events in response to user actions (such as clicking a button) and event listeners attached to the components handle the events (for example, by updating a database). Instead of implementing and registering listeners for each component, most JSF applications take advantage of shortcuts in the form of method bindings. A method binding is similar to a value binding, but it binds a component to an application method instead of an application property value. For instance, the UICommand component has a property that takes a method binding value. When the component fires an ActionEvent, a default ActionListener provided by JSF and automatically attached to the component invokes the method that the method binding points to. All the component writer needs to do is implement the method.

For the subscription example application, let's say that the component writer implements the action event processing method in a new class called SubscriberHandler:

package com.mycompany.newsservice.handlers;



import com.mycompany.newsservice.models.Subscriber;



public class SubscriberHandler {

    private Subscriber subscriber;



    public void setSubscriber(Subscriber subscriber) {

        this.subscriber = subscriber;

    }



    public String saveSubscriber( ) {

        subscriber.save( );

        return "success";

    }

}

The SubscriberHandler class has two methods: a setter method for associating it with an instance of the Subscriber class and a method for handling the Save button ActionEvent. The saveSubscriber() method simply calls the save() method on the Subscriber instance and returns success. In a real application, it would return one or more other values if things didn't go as planned, e.g., systemFailure if the database wasn't available.

It may seem like overkill to create a new class with the only purpose of calling a method in the application backend class, and in this simple example, it probably is. As you'll see when we start implementing a more complex application, there's a lot more that typically goes into this type of class. Its main purpose is to bridge the gap between the pure application objects and JSF components. For instance, it would be a bit odd for the save() method in Subscriber to return a String, but it serves a purpose for a JSF action event processing method to do so, because JSF can use the returned value to decide what to do next. But let's save that for later and move on to the next component writer task.

JSF creates and configures instances of application classes, such as the Subscriber and SubscriberHandler classes, based on information specified in a configuration file named faces-config.xml. It makes the instances available through variables that the page author uses in value and method binding expressions, as you'll see in the next section. Creating the configuration file is a task that also falls on the component writer's shoulders because it's part of tying the user interface and the backend together. Here's a snippet of the configuration file with the declarations for the example application classes:

<faces-config>

  ...

  <managed-bean>

    <managed-bean-name>subscr</managed-bean-name>

    <managed-bean-class>

      com.mycompany.newsservice.models.Subscriber

    </managed-bean-class>

    <managed-bean-scope>session</managed-bean-scope>

  </managed-bean>

  <managed-bean>

    <managed-bean-name>subscrHandler</managed-bean-name>

    <managed-bean-class>

      com.mycompany.newsservice.handlers.SubscriberHandler

    </managed-bean-class>

    <managed-bean-scope>request</managed-bean-scope>

    <managed-property>

      <property-name>subscriber</property-name>

      <value>#{subscr}</value>

    </managed-property>

  </managed-bean>

  ...

</faces-config>

As is customary these days, the configuration file is an XML document. The application objects are declared by <managed-bean> elements. The first <managed-bean> element declares that an instance of the Subscriber class should be made available as a session scope variable named subscr. I'll get back to the scope in Chapter 4, but declaring the scope as session (as in this example) means that a unique instance is created for each user and remains available as long as the user actively uses the application.

The second <managed-bean> element contains a similar declaration of a variable named subscrHandler as an instance of the SubscriberHandler, but it also contains a <managed-property> element, saying that its subscriber property must be initialized with the value of the subscr variable. This is how the SubscriberHandler instance is linked to the Subscriber instance.

    Previous Section  < Day Day Up >  Next Section