JAVA

Friday, May 6, 2011

JASPER REPORTS TUTORIALS

WWW.jasperforge.org

ntroduction
JasperReports is a powerful open source reporting tool that has the ability to deliver rich content onto the screen, to the printer, or into PDF, HTML, XLS, RTF, ODT, CSV, TXT and XML files. It is entirely written in Java and can be used in a variety of Java-enabled applications to generate dynamic content. Its main purpose is to help create page-oriented, ready-to-print documents in a simple and flexible manner.
Top button


API Overview
JasperReports organizes data retrieved from a data source according to a report-design defined in a JRXML file. In order to fill a report with data, the report-design must be compiled first.
The compilation of the JRXML file representing the report-design is performed by the compileReport() method exposed by the JasperCompileManager class.
Through compilation, the report design is loaded into a report-design object that is then serialized and stored on disk ( JasperReport class). This serialized object is used when the application wants to fill the specified report-design with data. In fact, the compilation of a report-design implies the compilation of all Java expressions defined in the JRXML file representing the report design. Various verifications are made at compilation time, to check the report-design consistency. The result is a ready-to-fill report-design that will be used to generate documents on different sets of data.
In order to fill a report-design, one can use the fillReportXXX() methods exposed by theJasperFillManager class. Those methods receive as a parameter the report-design object, or a file representing the specified report-design object, in a serialized form, and also a JDBC connection to the database from which to retrieve the data to fill the report with. The result is an object that represents a ready-to-print document ( JasperPrint class) and that can be stored on disk in a serialized form (for later use), can be delivered to the printer or to the screen, or can be exported into a PDF, HTML, XLS, RTF, ODT, CSV, TXT or XML document.
These classes represent a façade to the JasperReports engine. They have various static methods that simplify the access to the API functionality and can be used to compile an JRXML report design, to fill a report, to print it, or to export to other document formats (PDF, HTML, XML).

In addition to these façade classes, you will also get to work directly with specific exporter classes, in case you need to export your reports to XLS, RTF, ODT, TXT or other document formats for which there is no corresponding helper method in the JasperExportManager, or when you need to configure the export process and adapt it to your specific needs. These exporter implementations can be found in the net.sf.jasperreports.engine.export package of the JasperReports library.

If you need to display the report inside a Swing application, you can use the JRViewer component that is shipped with the library and consists of an embeddable and configurable javax.swing.JPanel component.
The JasperViewer is a stand-alone Swing application that uses the JRViewer component to display reports in proprietary format (serialized JasperPrint objects) or in XML format.
To help with the report design work, JasperReports provides a report design previewer in theJasperDesignViewer class.
Top button



Report Designs
As mentioned, a report design represents a template that will be used by the JasperReports engine to deliver dynamic content to the printer, to the screen or to the Web. Data stored in the database is organized according to the report design to obtain ready to print, page oriented documents.
The report designs are defined in JRXML files and must have a special structure. This structure is declared in a DTD file supplied with the JasperReports engine. The JRXML files are then compiled, in order to use them in report filling operations.

To create a simple report design, we have to edit an XML file with the following structure:

PUBLIC "-//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

... 
To have a better understanding of the structure of a JRXML file, or of a report design in general, we recommend you to use the Quick Reference.
Top button



Compiling Report Designs
A report design is represented by a JRXML file that has the structure defined in the jasperreport.dtdfile, or by an in-memory JasperDesign object. In order to generate reports according to such a report design, this needs to be compiled. Report design compilation can be done using the compileReportXXX() methods exposed by the JasperCompileManager class and results into a *.jasper file or a JasperReport object.
When compiling a report design, the engine first performs a validation to ensure that the template (JasperDesign) is consistent and then transforms all the report expressions in a ready-to-evaluate form, storing them inside the resulting compiled report template (JasperReport or .jasper file).
This transformation implies either the on-the-fly compilation of a Java class file that will be associated with the report template, or the generation of a Groovy or BeanShell script to use when evaluating report expressions during the report filling process, depending on the specified report expression language for the report (see the language property of a report template).

Before reading more about report compilation, you should understand when do you need to compile your report templates and which is the best way to do it by reading the following FAQ:
When should I compile my report templates and how?.
To make report design compilation process as flexible as possible, a special interface calledJRCompiler was introduced.
As seen above, there are several different types of classes implementing this interface shipped with the library:

1. Java creport compilers. These report compilers generate and compile a Java class containing the report expressions evaluating methods; \\
2. The Groovy report compiler that generates a script for runtime report expressions evaluation.
3. The BeanShell report compiler that generates a script for runtime report expressions evaluation.
For more details about report compilation, check The Definitive Guide to JasperReports.

Ant task for compiling report designs

Since the report design compilation process is more like a design-time job than a runtime one, an Ant task was provided with the library in order to simplify development.
This Ant task is implemented by the JRAntCompileTask and is very similar to the Ant built-in task, as far as syntax and behavior are concerned.
The report design compilation task can be declared like this, in a project's build.xml file:
classname="net.sf.jasperreports.ant.JRAntCompileTask">


 
 
 
In the example above, the lib folder should contain the jasperreports-.jar file along with its required libraries (including the jdt-compiler-.jar, which is the recommended report compiler, in case you use Java as the report expression language).
This user-defined Ant task can be then used to compile multiple JRXML report design files in a single operation, by specifying the root directory that contains those files or by selecting them using file patterns. Attributes of the report design compilation task:
AttributeDescription
srcdirLocation of the JRXML report design files to compile. Required unless nested elements are present.
destdirLocation to store the compiled report design files (the same as the source directory by default).
compilerName of the class that implements the JRCompiler interface (optional).
xmlvalidationFlag to indicate if the XML validation should be performed on the source report design files (true by default).
tempdirLocation to store the temporary generated files (the current working directory by default).
keepjavaFlag to indicate if the temporary Java files generated on-the-fly should be kept and not deleted automatically (false by default).
The report design compilation task supports nested and elements, just like the Ant built-in task.

To see this in action, check the demo/samples/antcompile sample provided with the project source files.

Viewing a report design

Report designs can be viewed using the JasperDesignViewer application.
In its main() method, it receives the name of the file which contains the report design to view.
This can be the JRXML file itself, or the compiled report design (*.jasper file).
Top button


Filling Reports
A compiled report design can be used to generate reports by calling the fillReportXXX() methods of the JasperFillManager class. There are two flavours of the fill methods in this façade class. Some receive a java.sql.Connection object as the third parameter, and the others receive a JRDataSource object instead.

This is because most of the times reports are filled with data from a relational database to which we connect through JDBC and is very convenient to have the SQL query inside the report template itself. The JasperReports engine can use the connection passed in and execute the SQL query, thus producing a report data source for filling the report.
In cases where data is available in other forms, the fill methods receiving a data source are to be used.
Top button


View, Print and Export Reports
Generated reports can be viewed using the JasperViewer application. In its main() method, it receives the name of the file which contains the report to view.

Generated reports can be printed using the printReport(), printPage() or printPages() static methods exposed by the JasperPrintManager class.

After having filled a report, we can also export it in PDF, HTML or XML format using the exportReportXXX() methods of the JasperExportManager class.
Top button


Parameters
Parameters are object references that are passed-in to the report filling operations. They are very useful for passing to the report engine data that it can not normally find in its data source. For example, we could pass to the report engine the name of the user that has launched the report filling operation if we want it to appear on the report, or we could dynamically change the title of our report.

An important aspect is the use of report parameters in the query string of the report, in order to be able to further customize the data set retrieved from the database. Those parameters could act like dynamic filters in the query that supplies data for the report.
Declaring a parameter in a report design is very simple and it requires specifying only its name and its class:


There are two possible ways to use parameters in the query:

1. The parameters are used like normal java.sql.PreparedStatement parameters using the following syntax:

SELECT * FROM Orders WHERE CustomerID = $P{OrderCustomer}

2. Sometimes is useful to use parameters to dynamically modify portions of the SQL query or to pass the entire SQL query as a parameter to the report filling routines. In such a case, the syntax differs a little, like in the following example:

SELECT * FROM Orders ORDER BY $P!{OrderByClause}

There are also the following built-in system parameters, ready to use in expressions:
Parameter NameDescription
REPORT_PARAMETERS_MAPThis parameter will contain a map with all user defined and built-in parameters
REPORT_PARAMETERS_MAPThis parameter will contain a map with all user defined and built-in parameters
REPORT_CONNECTIONA user supplied java.sql.Connection used for JDBC datasources
REPORT_DATA_SOURCEA user supplied instance of JRDataSource representing either one of the built-in data source types or a user-defined one
REPORT_MAX_COUNTAn integer allowing users to limit the datasource size
REPORT_SCRIPTLETJRAbstractScriptlet containing an instance of the report scriptlet provided by the user
REPORT_LOCALEA java.util.Locale instance containing the resource bundle desired locale
REPORT_RESOURCE_BUNDLEThe java.util.ResourceBundle containing localized messages
REPORT_TIME_ZONEA java.util.TimeZone instance to use for date formatting
REPORT_VIRTUALIZERThe JRVirtualizer object to be used for page virtualization
REPORT_CLASS_LOADERA java.lang.ClassLoader instance to be used during the report filling process to load resources such as images, fonts and subreport templates
IS_IGNORE_PAGINATIONIf set to java.lang.Boolean.TRUE the report will be generated on one long page and page break will not occur

Top button


Data Source
JasperReports support various types of data sources using a special interface calledJRDataSource.
There is a default implementation of this interface, the JRResultSetDataSource class, which wraps a java.sql.ResultSet object. It allows the use of any relational database through JDBC.
When using a JDBC data source, you could pass a java.sql.Connection object to the report filling operations and specify the query in the report definition itself (see the element in the XML file) or could create a new instance of the JRResultSetDataSource by supplying the java.sql.ResultSet object directly.
With other types of data sources, things should not be different and all you have to do is to implement the JRDataSource interface, or use one of the implemetations that are shipped with the JasperReports library to wrap in-memory collections or arrays of JavaBeans, CSV or XML files, etc.
Top button


Fields
Report fields represent the only way to map data from the data source into the report generating routines. When the data source of the report is a java.sql.ResultSet, all fields must map to corresponding columns in the java.sql.ResultSet object. That is, they must have the same name as the columns they map and a compatible type.
For example:
If we want to generate a report using data retrieved from the table Employees, which has the following structure:
Column NameDatatypeLength
EmployeeIDint4
LastNamevarchar20
FirstNamevarchar10
HireDatedatetime8
We can define the following fields in our report design:



If we declare a field that does not have a corresponding column in the java.sql.ResultSet, an exception will be thrown at runtime. Columns present in the java.sql.ResultSet object that do not have corresponding fields in the report design do not affect the report filling operations, but they also won't be accessible.
Top button


Expressions
Expressions are a powerful feature of JasperReports. They can be used for declaring report variables that perform various calculations, for data grouping on the report, to specify report text fields content or to further customize the appearance of objects on the report.
Basically, all report expressions are Java expressions that can reference report fields and report variables.
In an XML report design there are several elements that define expressions: , , , , and .
In order to use a report field reference in an expression, the name of the field must be put between $F{ and } character sequences.
For example, if we want to display in a text field, on the report, the concatenated values of two fields, we can define an expression like this one:

$F{FirstName} + " " + $F{LastName}
The expression can be even more complex:

$F{FirstName} + " " + $F{LastName} + " was hired on " +
(new SimpleDateFormat("MM/dd/yyyy")).format($F{HireDate}) + "."
To reference a variable in an expression, we must put the name of the variable between $V{ and } like in the example below:


"Total quantity : " + $V{QuantitySum} + " kg."
There is an equivalent syntax for using parameters in expressions. The name of the parameter should be put between $P{ and } like in the following example:

"Max Order ID is : " + $P{MaxOrderID}
Top button


Variables
A Report variable is a special objects build on top of an expression. Variables can be used to simplify the report design by declaring only once an expression that is heavily used throughout the report design or to perform various calculations on the corresponding expressions.
In its expression, a variable can reference other report variables, but only if those referenced variables were previously defined in the report design. So the order in which the variables are declared in a report design is important.
As mentioned, variables can perform built-in types of calculations on their corresponding expression values like : count, sum, average, lowest, highest, variance, etc.
A variable that performs the sum of the Quantity field should be declared like this:
class="java.lang.Double" calculation="Sum">
$F{Quantity}
For variables that perform calculation we can specify the level at which they are reinitialized. The default level is Report and it means that the variable is initialized only once at the beginning of the report and that it performs the specified calculation until the end of the report is reached. But we can choose a lower level of reset for our variables in order to perform calculation at page, column or group level.
For example, if we want to calculate the total quantity on each page, we should declare our variable like this:
resetType="Page" calculation="Sum">
$F{Quantity}
new Double(0)
Our variable will be initialized with zero at the beginning of each new page.
There are also the following built-in system variables, ready to use in expressions:
  • PAGE_NUMBER
  • COLUMN_NUMBER
  • REPORT_COUNT
  • PAGE_COUNT
  • COLUMN_COUNT
  • GroupName_COUNT
Documentation pending...

Top button


Report Sections
When building a report design we need to define the content and the layout of its sections. The entire structure of the report design is based on the following sections:
  • </li><li class="partext"><pageHeader></li><li class="partext"><columnHeader></li><li class="partext"><groupHeader></li><li class="partext"><detail></li><li class="partext"><groupFooter></li><li class="partext"><columnFooter></li><li class="partext"><pageFooter></li><li class="partext"><lastPageFooter></li><li class="partext"><summary></li><li class="partext"><noData</li></ul><p class="partext">Sections are portions of the report that have a specified height and width and can contain report objects like lines, rectangles, images or text fields.<br>When declaring the content and layout of a report section in an XML report design we use the generic element <band>.<br>This is how a page header declaration should look. It contains only a line object and a static text:<br></p><p class="partext"><pageHeader><br><band height="30"><br><rectangle><br><reportElement x="0" y="0" width="555" height="25"/><br><graphicElement/><br></rectangle><br><staticText><br><reportElement x="0" y="0" width="555" height="25"/><br><textElement textAlignment="Center"><br><font fontName="Helvetica" size="18"/><br></textElement><br><text>Northwind Order List</text><br></staticText><br></band><br></pageHeader></p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Frames<a name="Frames" id="Frames"></a></span><p class="partext">Sometimes a group of elements have to share a common background or have a common border around them. This was achieved by putting a rectangle behind them, but it did not work with the grid exporters since overlapping elements are not supported there. <br>The new frame element is recognized by the grid exporters and can be used to group elements together by nesting them inside a frame. Frames can be nested on an unlimited number of levels.</p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Groups<a name="Groups" id="Groups"></a></span><p class="partext">Groups represent a flexible way to organize data on a report. When filling a report, the JasperReports engine tests all the defined group expressions to see whether a group rupture has occurred and if so it introduces the corresponding <groupFooter> and <groupHeader> sections on the report. <br>We can have as many groups as we want on a report. The order of groups declared in a report design is important because groups contain each other. One group contains the following group and so on. When a larger group encounters a rupture, all subsequent groups are reinitialized. <br>When declaring a report group, along with its corresponding data grouping expression, we have to declare the two sections: the group's header section and the group's footer section. <br>See the <a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">Jasper Sample</a> report for an example on how to define groups.</p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Fonts and Unicode Support<a name="Fonts_Unicode" id="Fonts_Unicode"></a></span><p class="partext">Now you can create your reports in any language! <br>New attributes in the <font> element where introduced to allow the mapping between the Java fonts and the PDF fonts. PDF uses special font settings and there was no way to make use of them in the previous version of JasperReports. With the introduction of those new attributes, the users can specify what PDF specific font should be used to display different character sets (pdfFontName attribute), what is the type of the encoding (pdfEncoding attribute) and whether the font should be embedded in the PDF document or not (isPdfEmbedded). <br><br>To simplify the use of the font settings, a new element was introduced: <reportFont>. <br>Report fonts are report level font definitions that ca be used as default or base font settings in other font definitions throughout the entire report. Since the support for international characters is somehow tied to the <a href="http://www.lowagie.com/iText/" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">iText</a> library, you can find more details about how to create PDF documents in different languages and different character sets in the iText documentation.</p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Styles<a name="Styles" id="Styles"></a></span><p class="partext">Report styles were introduced in order to group together a set of visual properties that would then be applied to report elements that reference the report style. This new concept is an extension of the former report font concept which is now deprecated. Report elements that reference a report style definition could override the values of any visual property defined in the style.<br>Report styles could also reference other report styles and the same inheritance and override mechanism applies to them too. Styles are useful when a whole range of elements need to share the same visual properties and any change made to that has to apply to all of them. This can be achieved by changing the report style they all reference.</p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p> </p><p> </p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Scriptlets<a name="Scriptlets" id="Scriptlets"></a></span><p class="partext">All the data displayed on a report comes from the report parameters and from the report fields. This data can be processed using the report variables and their expressions. <br>There are specific moments in time when variable processing occurs. Some variables are initialized according to their reset type when the report starts, or when a page or column break is encountered, or when a group changes. Furthermore, variables are evaluated every time new data is fetched from the data source (for every row). <br>But only simple variable expressions cannot always implement complex functionality. This is where scriptlets intervene. <br>Scriptlets are sequences of Java code that are executed every time a report event occurs. Through scriptlets, users now have the possibility to affect the values stored by the report variables. <br>Since scriptlets work mainly with report variables, is important to have full control over the exact moment the scriptlet is executed. JasperReports allows the execution of custom Java code BEFORE or AFTER it initializes the report variables according to their reset type: Report, Page, Column or Group. <br>In order to make use of this functionality, users only have to create a scriptlet class by extending<a href="http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/JRAbstractScriptlet.html" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">JRAbstractScriptlet</a> class or <a href="http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/JRDefaultScriptlet.html" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">JRDefaultScriptlet</a> class. The name of this custom scriptlet class has to be specified in the scriptletClass attribute of the <jasperReport> element. <br>When creating a JasperReports scriptlet class, there are several methods that developers should implement or override, like: beforeReportInit(), afterReportInit(), beforePageInit(), afterPageInit(), beforeGroupInit(), afterGroupInit(), etc. Those methods will be called by the report engine at the appropriate time, when filling the report. <br>There is a default report parameter called REPORT_SCRIPTLET which represent a reference to the scriptlet object instantiated by the report engine when filling the report. It can be used in expressions throughout the report, to call custom methods on the scriptlet object, making the whole mechanism even more flexible. <br>And that is all! <br>See the <a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">ScriptletReport</a> sample for more details.</p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Subreports<a name="Subreports" id="Subreports"></a></span><p class="partext">Subreports are an important feature for a report-generating tool. They allow the creation of more complex reports and simplify the design work. <br>Subreports are very useful when creating master-detail type of reports, or when the structure of a single report is not sufficient to describe the complexity of the desired output document. <br>A subreport is in fact a normal report incorporated into another report. One can overlap subreports or create subreports containing subreports themselves, up to any nesting level. Any report template can be used as a subreport when incorporated into another report, without anything inside it having to change. <br>Like other report elements, the subreport element has an expression that is evaluated at runtime in order to obtain the source of the <a href="http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/JasperReport.html" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">JasperReport</a> object to load. <br>There are two ways to supply parameter values to a subreport. First, you can use the <parametersMapExpression> element which introducest the expression that will be evaluated to produce the specified parameters map. And/or you can supply the parameters individually using a <subreportParameter> element for each relevant parameter. When using simultaneously both ways to supply parameters the parameters values specified using <subreportParameter> will override values specified with <parametersMapExpression>. <br>Subreports require a data source in order to generate their content, just like normal reports, behave in the same way, and expect to receive the same kind of input when they are being filled. <br>Values calculated by a subreport can be returned to the parent report. More specifically, after a subreport is filled, values of the subreport variables can be either copied or accumulated (using an incrementer) to variables of the caller report (master variables). <br>See the <a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">Subreport</a> sample for details.</p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Internationalization<a name="I18n" id="I18n"></a></span><p class="partext">JasperReports allows associating a java.util.ResourceBundle with the report design, either at runtime, by using the new resourceBundle attribute or at runtime, by providing a value for the REPORT_RESOURCE_BUNDLE built-in parameter. <br>If the report needs to be generated in a locale that is different from the current locale, then the built-in REPORT_LOCALE parameter should be used to specify the runtime locale when filling the report. <br>In order to ease the internationalization of the reports there is a special syntax available inside report expressions that allows referencing String resources placed inside a java.util.ResourceBundle object associated with the report. The $R{...} syntax is for wrapping resource bundle keys in order to retrieve the value for that key. <br>For formatting messages in different languages, based on the report locale, there is a built-in method inside the <a href="http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/fill/JRCalculator.html" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">JRCalculator</a> associated with the report that offers functionality similar to the java.text.MessageFormat class. This method is called msg() and has 3 convenience signatures that allow using up to 3 message parameters in the messages. There is also the build-in str() method which is the equivalent of the $R{...} syntax inside the report expressions, giving access to the resource bundle content based on the report locale. <br>In the generated output, the library now keeps information about the text run direction so that documents generated in languages that have right-to-left writing (like Arabic and Hebrew) could be rendered properly. <br>Check the <a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">I18nReport</a> and <a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">UnicodeReport</a> samples for details.</p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Datasets<a name="Datasets" id="Datasets"></a></span><p class="partext">Charts and crosstabs sometimes need to use data which the containing report does not iterate though directly at fill time. This would be the case with data sources that have fields which could themselves be data sources for subreports. <br>In order to eliminate the need to use subreports to render a chart or a crosstab that would be fed with the nested data, a new concept called a dataset was introduced. A dataset is something between a data source and a subreport because it contains parameters, fields, variables and groups, but no layout information. Check /demos/samples/charts and the <a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">Crosstabs sample</a>.</p></td><td width="100" align="center" valign="bottom"><a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#top" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; "><img src="http://jasperforge.org/uploads/publish/jasperreportswebsite/JR%20Website/images/backtotop.gif" alt="Top button" width="47" height="17" border="0"></a></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Charts<a name="Charts" id="Charts"></a></span><p><span class="partext">JasperReports now has built-in support for charts. There is a new, ready-to-use chart component, although we already had images, text fields, subreports and other elements. This greatly simplifies the way charts are included inside reports, because previously the user had to completely rely on scriptlets in order to gather the chart data and render the chart using an image element in the report template.<br>Now with the new chart component, the user only has to make the desired visual settings and define the expressions that will help the engine build up the chart dataset in an incremental fashion during the iteration through the report data source.<br>When including and configuring a chart component, there are three entities involved:</span></p><ul><li class="partext">the overall chart component;</li><li class="partext">the chart dataset (groups chart data related settings);</li><li class="partext">the chart plot (groups visual settings related to the way the chart items are rendered)</li></ul><p class="partext">JasperReports currently supports the following types of charts:<br>Pie, Pie 3D, Bar, Bar 3D, XY Bar, Stacked Bar, Stacked Bar 3D, Line, XY Line, Area, XY Area, Scatter Plot, Bubble, Time series, High Low Open Close, Candlestick.<br>These types of charts use several types of datasets (each type of chart works with certain types of datasets): Pie Dataset, Category Dataset, XY Dataset, Time Series, Time Period Values, XYZ Dataset, High Low Dataset.<br>For all charts we can configure the following:</p><ul><li class="partext">border around all sides</li><li class="partext">background color</li><li class="partext">title</li><li class="partext">title position (top, left, bottom, right)</li><li class="partext">title font</li><li class="partext">title color</li><li class="partext">subtitle</li><li class="partext">subtitle font</li><li class="partext">subtitle color</li><li class="partext">show/hide legend</li><li class="partext">plot area background color</li><li class="partext">plot area background transparency (alpha)</li><li class="partext">plot area foreground transparency (alpha)</li><li class="partext">plot orientation (vertical, horizontal)</li><li class="partext">axis labels</li></ul><p> </p><p class="partext">For all datasets we can configure:</p><ul><li class="partext">increment type (detail, column, page, group, report)</li><li class="partext">increment group</li><li class="partext">reset type (none, column, page, group, report)</li><li class="partext">reset group</li></ul><p> </p><p class="partext">Specific settings by chart type:</p><ul><li class="partext">Pie 3D</li><ul><li class="partext">depth factor</li></ul><li class="partext">Bar, XY Bar, Stacked Bar</li><ul><li class="partext">hide/show labels</li><li class="partext">hide/show tick marks</li><li class="partext">hide/show tick labels</li></ul><li class="partext">Bar 3D, Stacked Bar 3D</li><ul><li class="partext">hide/show labels</li><li class="partext">x offset (3D effect)</li><li class="partext">y offset (3D effect)</li></ul><li class="partext">Line, XY Line, Scatter Plot, Time series</li><ul><li class="partext">hide/show lines</li><li class="partext">hide/show shapes</li></ul><li class="partext">Bubble</li><ul><li class="partext">scale type (both axes, domain axis, range axis)</li></ul><li class="partext">High Low Open Close</li><ul><li class="partext">hide/show close ticks</li><li class="partext">hide/show open ticks</li></ul><li class="partext">Candlestick</li><ul><li class="partext">hide/show volume</li></ul></ul><span class="partext">JasperReports uses the <a href="http://www.jfree.org/jfreechart/" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">JFreeChart</a> library to render the charts. Details about how to use this functionality can be found in the supplied <a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">JFreeChart Sample</a>.</span><p><br></p><p class="partext"> </p></td><td width="100" align="center" valign="bottom"><br></td></tr></tbody></table><p><br><br></p><table width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td><span class="pagesubtitle">Crosstabs<a name="Crosstabs" id="Crosstabs"></a></span><p class="partext">Crosstabs are a special type of table component in which both the rows and the columns are dynamic. They are used to display aggregated data using tables with multiple levels of grouping for both columns and groups. <br>For more details, check the <a href="http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_tutorial.html#" target="_blank" class="bulttextlink" style="font-family: Arial; font-size: 11px; color: rgb(28, 112, 171); text-decoration: none; ">crosstabs sample</a> provided.</p></td></tr></tbody></table></span></DIV>

GOOGLE

JSF LIFE CYCLE PHASES

Fast menu Listen and debug JSF lifecycle phases Basic debug example The first call The form submit Add immediate="true" to UIInput only Add immediate="true" to UICommand only Add immediate="true" to UIInput and UICommand Conversion error Validation error Okay, when should I use the immediate attribute?


Listen and debug JSF lifecycle phases

The JSF lifecycle will be explained and debugged here using the "poor man's debugging" approach with sysout's. We'll also check what happens if you add immediate="true" to the UIInput and UICommand and what happens when a ConverterException and ValidatorException will be thrown.



Well, you probably already know that the JSF lifecycle contains 6 phases:



1.Restore view

2.Apply request values

3.Process validations

4.Update model values

5.Invoke application

6.Render response

You can use a PhaseListener to trace the phases of the JSF lifecycle and execute some processes where required. But you can also use a "dummy" PhaseListener to debug the phases to see what is happening in which phase. Here is a basic example of such a LifeCycleListener:



Note: if you don't have a JSF playground environment setup yet, then you may find this tutorial useful as well: JSF tutorial with Eclipse and Tomcat.



package mypackage;



import javax.faces.event.PhaseEvent;

import javax.faces.event.PhaseId;

import javax.faces.event.PhaseListener;



public class LifeCycleListener implements PhaseListener {



public PhaseId getPhaseId() {

return PhaseId.ANY_PHASE;

}



public void beforePhase(PhaseEvent event) {

System.out.println("START PHASE " + event.getPhaseId());

}



public void afterPhase(PhaseEvent event) {

System.out.println("END PHASE " + event.getPhaseId());

}



}Add the following lines to the faces-config.xml to activate the LifeCycleListener.





mypackage.LifeCycleListener

This produces like the following in the system output:



START PHASE RESTORE_VIEW 1

END PHASE RESTORE_VIEW 1

START PHASE APPLY_REQUEST_VALUES 2

END PHASE APPLY_REQUEST_VALUES 2

START PHASE PROCESS_VALIDATIONS 3

END PHASE PROCESS_VALIDATIONS 3

START PHASE UPDATE_MODEL_VALUES 4

END PHASE UPDATE_MODEL_VALUES 4

START PHASE INVOKE_APPLICATION 5

END PHASE INVOKE_APPLICATION 5

START PHASE RENDER_RESPONSE 6

END PHASE RENDER_RESPONSE 6





Back to top

Basic debug example

To trace all phases of the JSF lifecycle, here is some sample code which represents simple JSF form with a "dummy" converter and validator and the appropriate backing bean. The code sample can be used to give us more insights into the phases of the JSF lifecycle, to understand it and to learn about it.



The minimal contents of the test JSF file: test.jsp











"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">



The dummy converter: MyConverter.java















binding="#{myBean.inputComponent}"

value="#{myBean.inputValue}"

valueChangeListener="#{myBean.inputChanged}">









value="submit"

action="#{myBean.action}" />



binding="#{myBean.outputComponent}"

value="#{myBean.outputValue}" />













package mypackage;



import javax.faces.component.UIComponent;

import javax.faces.context.FacesContext;

import javax.faces.convert.Converter;



public class MyConverter implements Converter {



public Object getAsObject(FacesContext context, UIComponent component, String value) {

System.out.println("MyConverter getAsObject: " + value);

return value;

}



public String getAsString(FacesContext context, UIComponent component, Object value) {

System.out.println("MyConverter getAsString: " + value);

return (String) value;

}



}The dummy validator: MyValidator.java



package mypackage;



import javax.faces.component.UIComponent;

import javax.faces.context.FacesContext;

import javax.faces.validator.Validator;

import javax.faces.validator.ValidatorException;



public class MyValidator implements Validator {



public void validate(FacesContext context, UIComponent component, Object value)

throws ValidatorException

{

System.out.println("MyValidator validate: " + value);

}



}The backing bean: MyBean.java



package mypackage;



import javax.faces.component.html.HtmlInputText;

import javax.faces.component.html.HtmlOutputText;

import javax.faces.event.ValueChangeEvent;



public class MyBean {



// Init ----------------------------------------------------------------------------------------



private HtmlInputText inputComponent;

private String inputValue;

private HtmlOutputText outputComponent;

private String outputValue;



// Constructors -------------------------------------------------------------------------------



public MyBean() {

log("constructed");

}



// Actions ------------------------------------------------------------------------------------



public void action() {

outputValue = inputValue;

log("succes");

}



// Getters ------------------------------------------------------------------------------------



public HtmlInputText getInputComponent() {

log(inputComponent);

return inputComponent;

}



public String getInputValue() {

log(inputValue);

return inputValue;

}



public HtmlOutputText getOutputComponent() {

log(outputComponent);

return outputComponent;

}



public String getOutputValue() {

log(outputValue);

return outputValue;

}



// Setters ------------------------------------------------------------------------------------



public void setInputComponent(HtmlInputText inputComponent) {

log(inputComponent);

this.inputComponent = inputComponent;

}



public void setInputValue(String inputValue) {

log(inputValue);

this.inputValue = inputValue;

}



public void setOutputComponent(HtmlOutputText outputComponent) {

log(outputComponent);

this.outputComponent = outputComponent;

}



// Listeners ----------------------------------------------------------------------------------



public void inputChanged(ValueChangeEvent event) {

log(event.getOldValue() + " to " + event.getNewValue());

}



// Helpers ------------------------------------------------------------------------------------



private void log(Object object) {

String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();

System.out.println("MyBean " + methodName + ": " + object);

}

}

The minimal faces configuration: faces-config.xml





myConverter

mypackage.MyConverter





myValidator

mypackage.MyValidator





myBean

mypackage.MyBean

request

Back to top

The first call

The first call in a freshly started webapplication with a fresh session should output at least:



START PHASE RESTORE_VIEW 1

END PHASE RESTORE_VIEW 1

START PHASE RENDER_RESPONSE 6

MyBean : constructed

MyBean getInputComponent: null

MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57

MyBean getInputValue: null

MyBean getOutputComponent: null

MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56

MyBean getOutputValue: null

END PHASE RENDER_RESPONSE 6





1. Restore view.

As the session is fresh, there's no means of any UIViewRoot to restore, so nothing to see here.



2. Apply request values.

This phase is skipped because there is no form submit.



3. Process validations.

This phase is skipped because there is no form submit.



4. Update model values.

This phase is skipped because there is no form submit.



5. Invoke application.

This phase is skipped because there is no form submit.



6. Render response.

The bean is constructed. Behind the scenes a new UIViewRoot is created and stored in the session. If the component binding getters returns precreated components (precreated in e.g. the constructor) and not null, then those will be used, otherwise JSF will create new components. The components will be stored in the UIViewRoot and the bounded components are set in the component bindings. The values to be shown are retrieved from the value binding getters in the backing bean. If the values aren't set yet, they defaults to null. The component bindings are not required by the way. Only use them if you actually need the component in the backing bean for other means than getting/setting the value. In this article they are included just to demonstrate what all happens in the lifecycle.



Back to top

The form submit

The form submit with the value "test" entered should output at least:



START PHASE RESTORE_VIEW 1

MyBean : constructed

MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57

MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56

END PHASE RESTORE_VIEW 1

START PHASE APPLY_REQUEST_VALUES 2

END PHASE APPLY_REQUEST_VALUES 2

START PHASE PROCESS_VALIDATIONS 3

MyConverter getAsObject: test

MyValidator validate: test

MyBean getInputValue: null

MyBean inputChanged: null to test

END PHASE PROCESS_VALIDATIONS 3

START PHASE UPDATE_MODEL_VALUES 4

MyBean setInputValue: test

END PHASE UPDATE_MODEL_VALUES 4

START PHASE INVOKE_APPLICATION 5

MyBean action: succes

END PHASE INVOKE_APPLICATION 5

START PHASE RENDER_RESPONSE 6

MyBean getInputValue: test

MyConverter getAsString: test

MyBean getOutputValue: test

END PHASE RENDER_RESPONSE 6





1. Restore view.

The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.



2. Apply request values.

Nothing to see here. Behind the scenes the submitted form values are obtained as request parameters and set in the relevant components in the UIViewRoot, for example inputComponent.setSubmittedValue("test").



3. Process validations.

The submitted values are passed through the converter getAsObject() method and validated by the validator. If the conversion and validation succeeds, then the initial input value will be retrieved from the value binding getter and behind the scenes the inputComponent.setValue(submittedValue) and inputComponent.setSubmittedValue(null) will be executed. If the retrieved initial input value differs from the submitted value, then the valueChangeListener method will be invoked.



4. Update model values.

The converted and validated values will now be set in the value binding setters of the backing bean. E.g. myBean.setInputValue(inputComponent.getValue()).



5. Invoke application.

The real processing of the form submission happens here.



6. Render response.

The values to be shown are retrieved from the value binding getters in the backing bean. If a converter is definied, then the value will be passed through the converter getAsString() method and the result will be shown in the form.



Back to top

Add immediate="true" to UIInput only

Extend the h:inputText in the test.jsp with immediate="true":



...



binding="#{myBean.inputComponent}"

value="#{myBean.inputValue}"

valueChangeListener="#{myBean.inputChanged}"

immediate="true">

...The form submit with the value "test" entered should output at least:



START PHASE RESTORE_VIEW 1

MyBean : constructed

MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57

MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56

END PHASE RESTORE_VIEW 1

START PHASE APPLY_REQUEST_VALUES 2

MyConverter getAsObject: test

MyValidator validate: test

MyBean getInputValue: null

MyBean inputChanged: null to test

END PHASE APPLY_REQUEST_VALUES 2

START PHASE PROCESS_VALIDATIONS 3

END PHASE PROCESS_VALIDATIONS 3

START PHASE UPDATE_MODEL_VALUES 4

MyBean setInputValue: test

END PHASE UPDATE_MODEL_VALUES 4

START PHASE INVOKE_APPLICATION 5

MyBean action: succes

END PHASE INVOKE_APPLICATION 5

START PHASE RENDER_RESPONSE 6

MyBean getInputValue: test

MyConverter getAsString: test

MyBean getOutputValue: test

END PHASE RENDER_RESPONSE 6





1. Restore view.

The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.



2. Apply request values.

Behind the scenes the submitted form values are obtained as request parameters and set in the relevant components in the UIViewRoot, for example inputComponent.setSubmittedValue("test"). The submitted values are immediately passed through the converter getAsObject() method and validated by the validator. If the conversion and validation succeeds, then the initial input value will be retrieved from the value binding getter and behind the scenes the inputComponent.setValue(submittedValue) and inputComponent.setSubmittedValue(null) will be executed. If the retrieved initial input value differs from the submitted value, then the valueChangeListener method will be invoked. This all happens in this phase instead of the Process validations phase due to the immediate="true" in the h:inputText.



3. Process validations.

Nothing to see here. The conversion and validation is already processed in the Apply request values phase, before the values being put in the components. This is due to the immediate="true" in the h:inputText.



4. Update model values.

The converted and validated values will now be set in the value binding setters of the backing bean. E.g. myBean.setInputValue(inputComponent.getValue()).



5. Invoke application.

The real processing of the form submission happens here.



6. Render response.

The values to be shown are retrieved from the value binding getters in the backing bean. If a converter is definied, then the value will be passed through the converter getAsString() method and the result will be shown in the form.



Note for other components without immediate: any other UIInput components inside the same form which don't have immediate="true" set will just continue the lifecycle as usual.



Back to top

Add immediate="true" to UICommand only

Extend the h:commandButton in the test.jsp with immediate="true" (don't forget to remove from h:inputText):



...



value="submit"

action="#{myBean.action}"

immediate="true" />

...The form submit with the value "test" entered should output at least:



START PHASE RESTORE_VIEW 1

MyBean : constructed

MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57

MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56

END PHASE RESTORE_VIEW 1

START PHASE APPLY_REQUEST_VALUES 2

MyBean action: succes

END PHASE APPLY_REQUEST_VALUES 2

START PHASE RENDER_RESPONSE 6

MyBean getOutputValue: null

END PHASE RENDER_RESPONSE 6





1. Restore view.

The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.



2. Apply request values.

The real processing of the form submission happens here. This happens in this phase instead of the Invoke application phase due to the immediate="true" in the h:commandButton. The UIInput components which don't have immediate="true" set will not be converted, validated nor updated, but behind the scenes the inputComponent.setSubmittedValue(submittedValue) will be executed before the action() method will be executed.



3. Process validations.

This phase is skipped due to the immediate="true" in the h:commandButton.



4. Update model values.

This phase is skipped due to the immediate="true" in the h:commandButton.



5. Invoke application.

This phase is skipped due to the immediate="true" in the h:commandButton.



6. Render response.

The values to be shown are retrieved from the value binding getters in the backing bean, expect for the UIInput components which don't have immediate="true" set. Behind the scenes those will be retrieved from the components in the UIViewRoot, e.g. inputComponent.getSubmittedValue().



Note for all components without immediate: as the Update model values phase is skipped, the value bindings aren't been set and the value binding getters will return null. But the values are still available as submitted value of the relevant components in the UIViewRoot. In this case you can retrieve the non-converted and non-validated input value from inputComponent.getSubmittedValue() in the action() method. You could even change it using inputComponent.setSubmittedValue(newValue) in the action() method.



Back to top

Add immediate="true" to UIInput and UICommand

Extend the h:inputText as well as the h:commandButton in the test.jsp with immediate="true":



...



binding="#{myBean.inputComponent}"

value="#{myBean.inputValue}"

valueChangeListener="#{myBean.inputChanged}"

immediate="true">

...



value="submit"

action="#{myBean.action}"

immediate="true" />

...The form submit with the value "test" entered should output at least:



START PHASE RESTORE_VIEW 1

MyBean : constructed

MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57

MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56

END PHASE RESTORE_VIEW 1

START PHASE APPLY_REQUEST_VALUES 2

MyConverter getAsObject: test

MyValidator validate: test

MyBean getInputValue: null

MyBean inputChanged: null to test

MyBean action: succes

END PHASE APPLY_REQUEST_VALUES 2

START PHASE RENDER_RESPONSE 6

MyConverter getAsString: test

MyBean getOutputValue: null

END PHASE RENDER_RESPONSE 6





1. Restore view.

The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.



2. Apply request values.

Behind the scenes the submitted form values are obtained as request parameters and set in the relevant components in the UIViewRoot, for example inputComponent.setSubmittedValue("test"). The submitted values are immediately passed through the converter getAsObject() method and validated by the validator. If the conversion and validation succeeds, then the initial input value will be retrieved from the value binding getter and behind the scenes the inputComponent.setValue(submittedValue) and inputComponent.setSubmittedValue(null) will be executed. If the retrieved initial input value differs from the submitted value, then the valueChangeListener method will be invoked. This all happens in this phase instead of the Process validations phase due to the immediate="true" in the h:inputText. Finally the real processing of the form submission happens here. This happens in this phase instead of the Invoke application phase due to the immediate="true" in the h:commandButton.



3. Process validations.

This phase is skipped due to the immediate="true" in the h:commandButton.



4. Update model values.

This phase is skipped due to the immediate="true" in the h:commandButton.



5. Invoke application.

This phase is skipped due to the immediate="true" in the h:commandButton.



6. Render response.

The values to be shown are retrieved from the value binding getters in the backing bean. If a converter is definied, then the value will be passed through the converter getAsString() method and the result will be shown in the form.



Note for all components with immediate: as the Update model values phase is skipped, the value bindings aren't been set and the value binding getters will return null. But the values are still available by the relevant components in the UIViewRoot. In this case you can retrieve the input value from inputComponent.getValue() in the action() method. The new input value is also available by the ValueChangeEvent in the inputChanged() method. You could even change it using inputComponent.setValue(newValue) in the action() method.



Note for other components without immediate: any other UIInput components inside the same form which don't have immediate="true" set will not be converted, validated nor updated, but behind the scenes the inputComponent.setSubmittedValue(submittedValue) will be executed before the action() method will be executed. You can retrieve the non-converted and non-validated input value from inputComponent.getSubmittedValue() in the action() method. You could even change it using inputComponent.setSubmittedValue(newValue) in the action() method.



Back to top

Conversion error

Let's see what happens if a conversion error will occur. Change the getAsObject() method of MyConverter.java as follows (and remove the immediate="true" from the test.jsp file):



package mypackage;



import javax.faces.component.UIComponent;

import javax.faces.context.FacesContext;

import javax.faces.convert.Converter;

import javax.faces.convert.ConverterException;



public class MyConverter implements Converter {



public Object getAsObject(FacesContext context, UIComponent component, String value) {

System.out.println("MyConverter getAsObject: " + value);

throw new ConverterException("Conversion failed.");

}



...

}The form submit with the value "test" entered should output at least:



START PHASE RESTORE_VIEW 1

MyBean : constructed

MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57

MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56

END PHASE RESTORE_VIEW 1

START PHASE APPLY_REQUEST_VALUES 2

END PHASE APPLY_REQUEST_VALUES 2

START PHASE PROCESS_VALIDATIONS 3

MyConverter getAsObject: test

END PHASE PROCESS_VALIDATIONS 3

START PHASE RENDER_RESPONSE 6

MyBean getOutputValue: null

END PHASE RENDER_RESPONSE 6





1. Restore view.

The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.



2. Apply request values.

Nothing to see here. Behind the scenes the submitted form values are obtained as request parameters and set in the relevant components in the UIViewRoot, for example inputComponent.setSubmittedValue("test").



3. Process validations.

The submitted values are passed through the converter getAsObject() method, where a ConverterException is thrown. The validator and the valueChangeListener are bypassed. Also the inputComponent.setValue(submittedValue) won't take place. The lifecycle will proceed to the Render response phase immediately.



4. Update model values.

This phase is skipped due to the ConverterException.



5. Invoke application.

This phase is skipped due to the ConverterException.



6. Render response.

The values to be shown are retrieved from the value binding getters in the backing bean, expecting the values for which a ConverterException has occurred. Behind the scenes those will be retrieved from the components in the UIViewRoot, e.g. inputComponent.getSubmittedValue().



Note: any other UIInput components inside the same form which don't throw a ConverterException will continue the lifecycle as usual, only the invoke application phase will still be skipped.



Back to top

Validation error

Let's see what happens if a validation error will occur. Change the validate() method of MyValidator.java as follows (and remove the immediate="true" from the test.jsp file and revert MyConverter.java back to original):



package mypackage;



import javax.faces.application.FacesMessage;

import javax.faces.component.UIComponent;

import javax.faces.context.FacesContext;

import javax.faces.validator.Validator;

import javax.faces.validator.ValidatorException;



public class MyValidator implements Validator {



public void validate(FacesContext context, UIComponent component, Object value)

throws ValidatorException

{

System.out.println("MyValidator validate: " + value);

throw new ValidatorException(new FacesMessage("Validation failed."));

}



}The form submit with the value "test" entered should output at least:



START PHASE RESTORE_VIEW 1

MyBean : constructed

MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57

MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56

END PHASE RESTORE_VIEW 1

START PHASE APPLY_REQUEST_VALUES 2

END PHASE APPLY_REQUEST_VALUES 2

START PHASE PROCESS_VALIDATIONS 3

MyConverter getAsObject: test

MyValidator validate: test

END PHASE PROCESS_VALIDATIONS 3

START PHASE RENDER_RESPONSE 6

MyBean getOutputValue: null

END PHASE RENDER_RESPONSE 6





1. Restore view.

The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.



2. Apply request values.

Nothing to see here. Behind the scenes the submitted form values are obtained as request parameters and set in the relevant components in the UIViewRoot, for example inputComponent.setSubmittedValue("test").



3. Process validations.

The values are retrieved as objects from the components, passed through the converter getAsObject() method and validated by the validator, where a ValidatorException is thrown. The valueChangeListener is bypassed. Also the inputComponent.setValue(submittedValue) won't take place. The lifecycle will proceed to the Render response phase immediately.



4. Update model values.

This phase is skipped due to the ValidatorException.



5. Invoke application.

This phase is skipped due to the ValidatorException.



6. Render response.

The values to be shown are retrieved from the value binding getters in the backing bean, expect of the values for which a ValidatorException has occurred. Behind the scenes those will be retrieved from the components in the UIViewRoot, e.g. inputComponent.getSubmittedValue().



Note: any other UIInput components inside the same form which don't throw a ValidatorException will continue the lifecycle as usual, only the invoke application phase will still be skipped.



Back to top

Okay, when should I use the immediate attribute?

If it isn't entirely clear yet, here's a summary, complete with real world use examples when they may be beneficial:



•If set in UIInput(s) only, the process validations phase will be taken place in apply request values phase instead. Use this to prioritize validation for the UIInput component(s) in question. When validation/conversion fails for any of them, the non-immediate components won't be validated/converted.

•If set in UICommand only, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s). Use this to skip the entire processing of the form. E.g. "Cancel" or "Back" button.

•If set in both UIInput and UICommand components, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s) which does not have this attribute set. Use this to skip the processing of the entire form expect for certain fields (with immediate). E.g. "Password forgotten" button in a login form with a required and immediate username field and a required but non-immediate password field.