The Theme and Woodstock Web Applications - Version @THEMEVERSION@

The Theme Infrastructure

10 The Woodstock com.sun.webui.theme Package

10.1 The ThemeContext Class

10.2 The ServletThemeContext Class

10.3 The ThemeServlet Class

10.4 The ResourceBundleTheme Class

10.5 The SPIThemeFactory Class

10.6 The ThemeService Class

10 The Woodstock com.sun.webui.theme Package

This package defines interfaces and some concrete classes. It is responsible for defining the theme's policies and behavior. The package is delivered in webui-jsf.jar file but there are no build time or runtime dependencies on the components or JSF. In fact it can be delivered in a separate jar file. It is currently not delivered in a separate jar file, as a convenience to web application developers, in order to reduce the total number of jar files required by a Woodstock web application.

10.1 The ThemeContext Class

The ThemeContext interface defines a set of methods and properties to provide a programming layer above the components and application, to control the runtime environment of the Theme infrastructure. The motivation for this interface resulted from the idea of a "console" controlling the theme of applications it served. For example if the "console" owned the theme resources and made them available on the class path of its applications, it would be the theme that was referenced by the running applications. For example the "console" could control the theme name, the theme factory instance, and the class loader referenced by the theme infrastructure at runtime.

This works because no application can be started without the console's knowledge. The "console" creates an instance of ThemeContext and places it in the runtime environment such that the theme runtime references that instance. In a Servlet environment the "console" would place the instance in the ServletContext.

For more detailed information see ThemeContext javadoc.

10.2 The ServletThemeContext Class

The ThemeServletContext is a concrete subclass of ThemeContext and it expresses the properties of the ThemeContext as context-param elements. This enables the web application to control the runtime environment of the theme by declaring these context-param elements with the desired values in the application's web.xml file.

The "console" control as discussed in the previous section is still valid in the presence of context-param elements in an application's web.xml file. The console would be responsible for implementing a concrete subclass of ThemeContext, probably a subclass of ServletThemeContext. Its implementation would determine which context-param declared in an application's web.xml file was appropriate and would not interfere with its policies. The "console" would then make the ThemeContext instance available in the application's servlet context.

When a Woodstock component or renderer requires a theme resource the ThemeContext instance, made available by the "console", is obtained in an opaque manner, via ThemeContext interfaces. The "console" now has control over the theme that is eventually referenced, based on data contained in that instance of the a ThemeContext

For more detailed information see ServletThemeContext javadoc.

10.3 The ThemeServlet Class

Theme resources for the Woodstock components are delivered in a jar file, webui-jsf-suntheme.jar. This has several advantages.

Since the resources are in a jar file, a simple HTTP request cannot obtain the resource. Unfortunately the FacesServlet class is defined as final and therefore cannot be subclassed in order to implement the necessary behavior. Because of these two constraints a separate servlet must be configured by web applications that use the Woodstock components and its theme. This servlet simply uses the class's ClassLoader to load the resource and write it to the response. As I write this it occurs to me that a ThemeContext if available, should be used to obtain the class loader instance.

Requiring a web application to declare a separate servlet can lead to complications if the "default" url-pattern which is "/theme", conflicts with other servlets in the application. This can be addressed by specifying the com.sun.webui.theme.THEME_SERVLET_CONTEXT context-param to communicate the ThemeServlet's context path to the theme infrastructure. For example:

<-- The Theme Servlet declaration -->
<servlet>
    <servlet-name>ThemeServlet</servlet-name>
    <servlet-class>com.sun.webui.theme.ThemeServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>ThemeServlet</servlet-name>
    <url-pattern>/businesstheme/*</url-pattern>
</servlet-mapping>

<!-- The com.sun.webui.theme.THEME_SERVLET_CONTEXT that needs to
     reflect the url-pattern of the servlet mapping, without the "*" -->
<context-param>
    <param-name>com.sun.webui.theme.THEME_SERVLET_CONTEXT</param-name>
    <param-value>/businesstheme</param-value>
</context-param>
For more detailed information see ThemeServlet javadoc.

10.4 The ResourceBundleTheme Class

The ResourceBundleTheme class is concrete implementation of Theme and is responsible for obtaining theme data from Java ResourceBundles that contain theme data. This class also implicitly defines the categories of theme resources. These categories are

Within these categories are sets of keys that define theme data values. Some of these keys are implicitly defined by ResourceBundleTheme.ThemeBundle and ResourceBundleTheme.ThemeProperties.

This class also implements a "main" method for generating the Javascript client theme and its locale variants from an existing theme jar file. See Generating the Javascript Theme.

There is only one instance of this class created. A ThreadLocal ThemeResources instance is referenced by the ResourceBundleTheme instance to obtain requested theme properties.

For more detailed information see ResourceBundleTheme javadoc.

10.5 The SPIThemeFactory Class

The SPIThemeFactory class is a concrete implementation of ThemeFactory that recognizes ThemeService service provider implementations. The SPIThemeFactory is used to obtain ResourceBundleTheme instances.

SPIThemeFactory discovers SPI based themes and maintains a map of available themes based on theme name and version, and implements a "default" theme policy when a theme is requested without a specific name or version. That policy is simply; the default theme is the first theme that is discovered. When returning a theme, theme resources that are defined in the ThemeContext always have the highest precedence, in other words, those resources are always searched first, to resolve a request for a theme property.

A component, renderer or application calls the getTheme method to acquire a Theme instance. This can can include a theme name, locale and version. If none of these parameters are given the ThemeFactory's "default" theme policy will be used to determine the Theme instance to return.

A list of theme resources is assembled and is encapsulated in an instance of ThemeResources. The order of theme resources is significant. The ordering is based on the theme name and version as specified in the getTheme call. The ordering is as follows
  1. ThemeContext theme resources (defined implicitly or via a com.sun.webui.theme.THEME_RESOURCES context-param) will appear as ordered in the parameter value.
  2. If the theme name and version are specified in the call to getTheme ; the named resources in descending version order.
  3. If only the theme version is specified in the call to getTheme ; all available theme resources in descending version order.
  4. If only the theme name is specified in the call to getTheme ; named resources in descending version order.
  5. If neither theme name or theme version is specified in the call to getTheme; default theme resources in descending version order.

In all cases if a named theme or version is requested but not available then the default theme resources will be returned ordered in descending version order.

For more detailed information see SPIThemeFactory javadoc.

10.6 The ThemeService Class

The ThemeService class is an abstract class as per the design pattern for Java Service Providers sun.misc.service. An implementations of this service like SunthemeThemeService is included in a theme jar file as per the conventions defined by sun.misc.service.


META-INF/services/com.sun.webui.theme.ThemeService
com/sun/webui/jsf/suntheme/SunthemeThemeService.class

The contents of META-INF/services/com.sun.webui.theme.ThemeService

com.sun.webui.jsf.suntheme.SunthemeThemeService

The contents of SunthemeThemeService.java

/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License).  You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the license at
 * https://woodstock.dev.java.net/public/CDDLv1.0.html.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at https://woodstock.dev.java.net/public/CDDLv1.0.html.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
 */
package com.sun.webui.jsf.suntheme;

import com.sun.webui.theme.ThemeService;

public class SunthemeThemeService extends ThemeService {

    public SunthemeThemeService() {
        super();
    }

    public String[] getThemeBundles() {
        return new String[] { "com.sun.webui.jsf.suntheme.suntheme" };
    }
}

The contents of "com.sun.webui.jsf.suntheme.suntheme.properties"

Theme.name=suntheme
Theme.version=@THEMEVERSION@

# Defines a bundle
#
Theme.bundle.stylesheet=com.sun.webui.jsf.suntheme.properties.stylesheets

# Defines a bundle
#
Theme.bundle.messages=com.sun.webui.jsf.suntheme.messages.messages

# Defines a bundle
Theme.bundle.javascript=com.sun.webui.jsf.suntheme.properties.javascript

# Defines a bundle
#
Theme.bundle.stylesheet.classMapper=com.sun.webui.jsf.suntheme.properties.styles

# Defines a bundle
#
Theme.bundle.images=com.sun.webui.jsf.suntheme.properties.images

# Defines a bundle
#
Theme.bundle.template=com.sun.webui.jsf.suntheme.properties.templates


This service implements one method that returns an array of ResourceBundle base names that define information about a theme, namely, bundles that define theme properties in the theme categories as defined by ResourceBundleTheme. ThemeResources instances mentioned in the previous discussion contain the base names for these bundles.

For more detailed information see ResourceBundleTheme javadoc.