This document describes the JSF spec for implementing 313-DevLifecycle. A full implementation is attached to issue 313.
To understand this proposal from the API consumer's perspective, read the Use Cases section. To understand the proposal from the spec implementor's perspective, read the Specification Changes section.

Use Cases

At first glance, 313-DevLifecycle resembles using different log levels to control the verbosity of log output. In fact, 313-DevLifecycle is a superset of that feature. The state of the DevLifecycle flag would dictate a change in behavior that goes beyond simply deciding what kind of and how much information gets logged. Consider the following use cases.

JSF App Developer Use Case

Currently, if the user neglects to put an <h:messages> tag on their page, they miss out on error messages that may crop up during iterative development. The frequently given advice is: "put an <h:messages> element on every page during development and take it out or customize it when you get to deployment". But what if one forgets to do that? This feature is captured in 314-DevTimeMessages and it cannot be implemented without 313-DevLifecycle.

Tapestry's much vaunted "line precise error reporting" feature would be really great to have in JSF components. However, you wouldn't want to have that much developer level detail in the case of errors that happen at deployment time.

Component Developer Use Case

At the time of developing a custom component, one knows the failure states of various elements in the system. It would be nice to be able to share that information with the developer using the component, but only if the DevLifecycle flag is set appropriately.

Page Author Use Case

It is easy to read the value of the product lifecycle phase from EL:

Project Stage is 
    <c:out value="#{servletContext.projectStage}" />

NOTE: This assumes adding a JSP implicit object for the ServletContext called servletContext. Without this, it's much harder to make use of this value from JSP or other template markup.

NOTE: I also really think it would be useful to have ServletContext.getCurrentInstance() that uses ThreadLocal storage to make the ServletContext accessible from anywhere. See FacesContext.getCurrentInstance().

Specification Changes

Add a method to ServletContext

public String getProjectStage()

Return the product lifecycle phase for the currently running application instance. The default value is "PRODUCTION"
The implementation of this method must perform the following algorithm or an equivalent with the same end result to determine the value to return.

If the value has already been determined by a previous call to this method, simply return that value.
Otherwise look for an entry in the initParameter of the ServletContext with the key given by the value of java.servlet.ProjectStage

Issue: (Should we reserve all javax, com.sun sun init-param names in the spec?)
.

If this succeeds without exception, save the value and return it.

If not found, or any of the previous attempts to discover the constant value have failed, assign the value as PRODUCTION and return it.

Since:
3.0

The value of this state may be queried at any time after application startup by calling getProjectStage() on the ServletContext instance.

This value is immutable at runtime and is configured by a init-param. The value of param-name is the value of the ProjectStage. The default value if nothing is specified is PRODUCTION. The order of the elements for ProjectStage is

PRODUCTION, SYSTEM-TEST, UNIT-TEST, DEVELOPMENT
followed by any vendor specific definitions.

web.xml example

The constants: the java language identifiers of the enum members of this class, capitalized exactly as they appear in this file.

For example:

<init-param>
  <param-name>javax.servlet.ProjectStage</param-name>
  <param-value>UNIT-TEST</param-value>

</init-param>

In this case, ServletContext.getCurrentInstance().getProjectStage() returns UNIT-TEST

Values that every container MUST support

ProjectStage Value Description
DEVELOPMENT This value indicates the currently running application is right now, at this moment, being developed.
UNIT-TEST This value indicates the currently running application is undergoing unit testing.
SYSTEM-TEST This value indicates the currently running application is undergoing system testing.
PRODUCTION This value indicates the currently running application is deployed in production.


Issue: Should we allow an annotation to specify the ProjectStage? Or is it good enough to say that the default is PRODUCTION and if it has to be changed it must be in the descriptor. One proposed solution is the have an annotaiton based approach like defined below. Seeking the feedback of the EG.

Allow Servlet and Filter implementations to be annotated to specify ProjectStage

Because Servlet 3.0 need not always have a web.xml, there needs to be a simple way to set the value of the ProjectStage property directly in code. Let us add an attribute, "projectStage" to the @Servlet, and @Filter annotations. The value of the attribute is the same as what one would put as the value of the javax.servlet.ProjectStage init-param in the web.xml. We could also define a new annotation - @ProjectStage that allows users to set the value appropriately and can be reused by other specifications as well now and in the future. If multiple instances of these annotations are found by the annotation scanning routine, their values are collected in the list and the "lowest" one wins, based on the ordering defined above .