Are you running your web container on a Java SE 5 (code named "Tiger") or later JVM? If so, you can take advantage of several Shale features that are enabled by this underlying platform:
faces-config.xml
resource.ViewController
interface and provide methods
with the names defined by this interface.faces-config.xml
resource.shale-tiger.jar
in your web application.
In a traditional JavaServer Faces application, managed
beans must be declared in a faces-config.xml
resource supplied by the application. In many cases, the
supplied values are effectively constant -- for example, the
name that the managed bean is known by is a dependency for
other elements of the application (such as value binding
expressions). In such cases, it would be very useful to
be able to configure the managed bean name, and the scope
this bean should be stored in, directly in the bean source
code itself.
In addition to defining the characteristics of the managed
bean itself, you can also use the @Value
annotation to establish the initial value to which a
field should be set. (You must supply a corresponding public
property setter method.) This is not particularly useful
for setting literal values, because you can accomplish the
same result with a Java initialization expression on the
instance variable itself. However, it is very useful when
you want to specify an application-specific value binding
expression, without requiring the developer to explicitly
include the configuration in a faces-config.xml
resource.
In some scenarios, an application developer will still want
to override the characteristics that are specified via annotations.
For this reason, any configuration information in a
faces-config.xml
resource, for a particular
managed bean name, will override the corresponding
settings defined by annotations.
The View Controller feature of Shale provides event callback services for several interesting lifecycle events:
init
- Called when the view corresponding
to this class has been created or restored.preprocess
- Called if this view is the one
that will process a form submit.prerender
- Called immediately before this
view will be asked to render itself.destroy
- Called after rendering, for all
instances where init
was called.org.apache.shale.view.ViewController
interface,
with fixed method names for each callback. With the Shale Tiger
Extensions, however, this is no longer required (although it is,
of course, still supported).
Instead, you implement a backing bean class with no requirements
on extending a particular base class, or implementing a particular
interface. Instead, you use the @View
annotation on
the class itself to say that it is interested in view controller
callback events. Then, on any public method that takes no arguments,
you use the @Init
, @Preprocess
,
@Prerender
, or @Destroy
annotations
to request callbacks, to that particular method, when the corresponding
lifecycle event occurs. You are NOT required
to use a particular method name for these callbacks. In addition,
if your backing bean logic is not interested in one or more of the
view controller callbacks, you are NOT
required to
provide a method that is marked with the corresponding annotation.
A standard JavaServer Faces runtime environment allows an
application, or a component library, to register custom classes
as JavaServer Faces components, converters, renderers,and validators,
using the <component>
, <converter>
,
<renderer>
, and <validator>
elements, respectively, in a faces-config.xml
resource.
The Shale Tiger extensions allow the implementation classes for these
objects to register themselves by virtue of the existence of an
annotation on the class, without requiring a configuration resource
to be present. In each case, the class being registered must still
implement the corresponding JavaServer Faces API (for example, a
converter registered in this manner must still implement the
javax.faces.convert.Converter
interface).
To use any of the Shale Tiger Extensions in your application,
you MUST run your web container on a Java SE 5
or later container, and MUST include the
shale-tiger.jar
resource in your web application.
To optimize performance at application startup, the Shale Tiger Extensions will ONLY examine classes (to see if they include the appropriate annotations) in the following lcoations:
/WEB-INF/classes
./WEB-INF/lib
that
includes a META-INF/faces-config.xml
resource,
indicating that this JAR file is relevant to JavaServer Faces.@Bean
annotation on the class itself, and
set the managed bean name (required) and scope (optional). These
elements correspond to the <managed-bean-name>
and <managed-bean-scope>
elements in a
faces-config.xml
resource. Then, within the class,
you can optionally use the @Value
annotation on a
field to provide a literal value, or value binding expression,
that will provide the initial value for the corresponding property.
Putting it all together, you might end up with a class that looks like this:
package com.mycompany.mypackage; import org.apache.shale.tiger.managed.Bean; import org.apache.shale.tiger.managed.Scope; import org.apache.shale.tiger.managed.Property; // Define a managed bean named "mybean" to be put in session scope @Bean(name="mybean", scope=Scope.SESSION) public class MyBeanClass { // No required superclass or interface // Name a property that will be initialized via expression @Property(value="#{otherBean.otherProperty}") private String name = null; public String getName() { return this.name; } public void setName(String name) { this.name = name; } }
To use the Annotated View Controllers feature,
you must use the @View
annotation on the class
itself. Then, you can use the @Init
,
@Preprocess
, @Prerender
, and
@Destroy
annotations on the methods that you
wish to have notified when the corresponding lifecycle trips
occur. You need to implement only the callbacks you are
interested in (unlike the traditional implementation of an
interface, where you must provide implementations for all of
the defined method signatures).
A class that wishes to receive view controller callbacks via these annotations might look like this:
package com.mycompany.mypackage; import org.apache.shale.tiger.view.Init; import org.apache.shale.tiger.view.Preprocess; import org.apache.shale.tiger.view.View; @View public class MyBean { // No required superclass or interface // Name your init() method whatever you want @Init public void myInit() { ... } // Same with the prerender() method @Prerender public void justBeforeRendering() { ... } // This class is not interested in preprocess or destroy // methods, so they are not defined }
To use the Annotated Component Registration feature,
you must use annotations from the org.apache.shale.tiger.register
package, as illustrated below:
An annotated component registration should look like this:
package com.mycompany.mypackage; import javax.faces.component.UIComponentBase; import org.apache.shale.tiger.register.FacesComponent; @FacesComponent("my.component.type") public class MyComponent extends UIComponentBase { ... }
An annotated converter registration should look like this:
package com.mycompany.mypackage; import javax.faces.convert.Converter; import org.apache.shale.tiger.register.FacesConverter; @FacesConverter("my.converter.id") public class MyConverter implements Converter { ... }
An annotated renderer registration should look like this
(if the renderKitId
attribute is not specified,
the renderer will be registered with the standard HTML Basic
renderkit):
package com.mycompany.mypackage; import javax.faces.render.Renderer; import org.apache.shale.tiger.register.FacesRenderer; @FacesRenderer(renderKitId="my.render.kit.id", componentFamily="my.component.family", rendererType="my.renderer.type") public class MyRenderer extends Renderer { ... }
An annotated validator registration should look like this:
package com.mycompany.mypackage; import javax.faces.validator.Validator; import org.apache.shale.tiger.register.FacesValidator; @FacesValidator("my.validator.id") public class MyValidator implements Validator { ... }