Section 9.2. Building the Application Shell

team bbl


9.2. Building the Application Shell

Now that you've got Spring Rich up and running, you're ready to configure the main application window. You'll see how to configure the window's command bars, including the menu bar and tool bar. You'll also learn how Spring Rich lets you invoke a centralized GUI command through any number of actionable controls, which can trigger some action, like buttons or menu items. You'll also specify a logical command group, which you can reuse in any number of grouping controls. These are controls that let you group other actionable controls, like menus or command bars.

Once that soaks in, the following lab shows how to configure the main window's page area. The page will provide the central view into the RentABike inventory.

9.2.1. High-level application goals

Before going further with implementation, let's clarify the goals of the RentABike rich client that you'll build in this lab.


The user launches the Bike Store

The application presents a dazzling splash screen while the application loads.


The main window displays

The window's menu bar organizes your user's available commands into logical groups. The window's tool bar provides easy access to frequently needed commands. A "Bike Navigator" component displayed in a central page area provides a view into our current store inventory.


The user selects an existing bike for editing

The application presents a form that lets a user update a bike's properties. The form provides validation of the shop's business rules.


The user adds a new bike

Doing so displays a wizard, which lets the user enter bike properties validated against our Bike business rules.

Notice a few minor differences between this vision and the web-based clients that you've already used. You've already seen the splash screen. You'll also need to specify the command bars. Later, you'll see the rich validation and forms framework. In this lab, you'll focus on building the main window.

9.2.2. How do I do that?

To configure your main window, you first need to define several singleton beans that hold the context for your application. As usual, you'll leverage Spring for configuration and dependency injection.

As you've seen, a typical Spring Rich configuration will have three context definitions: a startup context, a root application context, and a child context for each application window. For now, focus on the root application context.

A single root application context defines your logical middle tier (Example 9-4). It's also where several Spring Rich services and descriptors are defined. Typically, the middle-tier business definitions are broken out into their own file, separate from the rich client-tier presentation definitions.

Example 9-4. business-layer-definitions.xml
<beans>     <bean name="rentABike" >         <property name="storeName"><value>Keith's Bikes</value></property>     </bean> </beans>

You've already seen the RentABike interface. Notice this context links to the ArrayListRentABike, which allows us to build and test the application without any database support (Example 9-5). Later, you'll be able to swap this implementation with one of the database implementations.

Example 9-5. com.springbook.richclient.richclient-definitions.xml
<beans>     <bean        >         <constructor-arg index="0">             <ref bean="applicationDescriptor"/>         </constructor-arg>         <constructor-arg index="1">             <ref bean="applicationLifecycleAdvisor"/>         </constructor-arg>     </bean>     <bean        >             <property name="name">                 <value>My RentABike</value>             </property>             <property name="version">                 <value>1.0</value>             </property>     </bean>          <bean       >         <property name="windowCommandBarDefinitions">             <value>               classpath:com/springbook/richclient/window-command-bars.xml             </value>         </property>         <property name="startingPageId">             <value>bikeNavigator</value>         </property>     </bean>

You see three bean definitions:


Application

The Application class is the central component in a set of application management abstractions in Spring Rich. You'll always define a single application bean for each of your Spring Rich apps.

Application is loaded at startup by the ApplicationLauncher to complete the startup initialization process. It issues callbacks at well-defined points within the application's lifecycle to the ApplicationLifecycleAdvisor below. It also provides a programmatic API for opening and closing application windows.


ApplicationDescriptor

Each application has an optional application descriptor, which provides the application's name, image, caption, description, version, build ID, and other metadata.


ApplicationLifecycleAdvisor

The lifecycle advisor allows convenient customization within well-defined points of a Spring Rich application's lifecycle. For example, before a new window is opened, a callback is issued allowing pre-window display configuration.

The next set of bean definitions select implementations of common services typical of most rich client applications:


Note: The component factory definition centralizes the production of Swing controls.
  <bean     />      <bean          >       <property name="basenames">         <list>           <value>org.springframework.richclient.application.messages</value>           <value>com.springbook.richclient.messages</value>         </list>       </property>   </bean>


Note: A Spring message source lets you externalize i18n messages from Java code.
  <bean      >      <property name="basenames">        <list>          <value>org.springframework.richclient.application.images</value>          <value>com.springbook.richclient.images</value>        </list>      </property>      <property name="brokenImageIndicator">         <value>classpath:/images/alert/error_obj.gif</value>      </property>   </bean>


Note: An optional Spring Rich Client image source lets you separate hard paths from your code.
  <bean      >     <property name="theme">       <bean />     </property>   </bean>

The next rich client bean definition deserves special attention because it is a bean post processor. Any bean post processor defined in the context will receive a call back after another bean is instantiated by Spring. That callback allows the insertion of custom processing for those beans.


Note: The optional LooksConfigurer definition lets you control the application's look and feelin this case, a jgoodies skin.

The applicationObjectConfigurer post processor below processes all beans that act as factories for controls to be displayed on the screen. Set it up like this, and you'll learn more below:

    <bean       >     </bean>

This applicationObjectConfigurer injects properties to visual descriptor beans. Essentially, these beans act as factories for GUI components rendering i18n messages, images, or icons.

To illustrate this in action, consider the applicationDescriptor bean you defined above. After Spring instantiates this descriptor, the applicationObjectConfigurer injects it localized properties, pulling them from the configured i18n sources.

In summary, the applicationObjectConfigurer gives you a powerful, consistent, automated configuration strategy for all of your GUI control factories.

9.2.2.1 Check point

Time for a check point. So far in this lab, you've created the root application context defining the business layer and several important rich client services. If you were to run your application now, by launching the RentABikeApplicationLauncher main method defined in the first lab, this is what you'd get:

org.springframework.richclient.application.ConfigurationException:  Unable to load window command bar definition at location:  [classpath: com/springbook/richclient/window-command-bars.xml]

The cause is simple. The RentABikeLifecycleAdvisor bean points to the above file for the configuration of the main window command bars, but the file doesn't yet exist. It's time to create that file so the main window will load successfully (Example 9-6).

To keep things simple, you'll add a menubar with a single "File" menu for now, and a tool bar with a shared "Save" command.

Example 9-6. com.springbook.richclient.window-command-bars.xml
<beans>      <bean      >      <property name="members">        <list>          <ref bean="fileMenu"/>        </list>      </property>   </bean>   <bean       >     <property name="members">       <list>         <ref bean="newMenu"/>         <value>separator</value>         <value>saveCommand</value>         <value>propertiesCommand</value>         <value>separator</value>         <bean />       </list>     </property>   </bean>   <bean      >      <property name="commandIds">        <list>          <value>saveCommand</value>          <value>propertyCommand</value>         </list>      </property>     </bean>   <bean       >     <property name="members">       <list>           <value>placeholder:newBikeCommand</value>       </list>     </property>   </bean>   <bean       >     <property name="members">       <list>         <ref bean="newMenu"/>         <value>saveCommand</value>       </list>     </property>   </bean> </beans>

That's it! Now if you were to run your application by launching the RentABikeApplicationLauncher main method defined in the first lab, you'd get Figure 9-1.

Figure 9-1. Rent-A-Bike main method


A generic application shell, with placeholders for our application-specific commands! Pretty easy, huh?!

9.2.3. What just happened?

How did the framework know that the newBikeCommand should be labeled "Bike" with a "B" mnemonic and a Ctrl-B accelerator key? You certainly didn't define any of that configuration above!

That leads us back to the application object configurer. Just as it can autoconfigure any control factory, it can also autoconfigure commands, pulling i18n metadata from the Spring configured message and image sources. For example, for the newBikeCommand above, the resource bundle files include the following:

newBikeCommand.label=&Bike@ctrl B newBikeCommand.caption=Creates a new bike newBikeCommand.icon=bullets/blue_diamond.gif

The framework handles all the configuration for you. No more manual configuration code!

You saw in this lab how to define the root context of a Spring Rich powered application, and how to configure the main window, including the window's "command bars." The result? A application shell with placeholders for the commands needed by your application, ready to customize in the next lab.

There's a lot going on behind the scenes to make things very convenient for you as a developer. The framework manages the entire lifecycle of your application, including opening a fully configured window populated with the command bars configured in the context file. The slick applicationObjectConfigurer autoconfigures beans for you that produce controls to be displayed on the screen, relieving you from having to configure them manually. In summary, boilerplate code is kept inside the framework, so you can focus on solving your domain problem.

Spring Rich GUI Commands

When your application starts up, the launcher delegates to the Application class, which opens the initial window. The window delegates to the lifecycle advisor to load its command-bar context, typically sourced from an externalized configuration file. Once loaded, the window asks the menuBar command group to produce a fully-populated JMenuBar. The window asks the toolBar command group to produce a fully-populated JToolBar.

Commands are not Swing controls! Commands are factories for producing Swing controls bound to a single controller action. ActionCommands produce actionable controls like JButtons, JMenuItems, JToggleButtons, JCheckBoxs, and JRadioButtons. CommandGroups produce grouping controls, like JMenus, JToolBars, and JMenuBars.

It bears repeating. As with struts, commands are not controls, but are controllers that should execute in response to UI events fired by bound controls. Any number of controls can bind to a single action command. Further, any number of grouping controls can bind to a single logical command group. In addition, manipulating the state of a single command automatically updates all bound controls.

This design keeps the Swing controls focused on presentation responsibilities and the signaling of user interface events, while the commands centralize controller logic that executes in response to those events.


    team bbl



    Spring. A developer's Notebook
    Spring: A Developers Notebook
    ISBN: 0596009100
    EAN: 2147483647
    Year: 2005
    Pages: 90

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net