JasperReports Ultimate Guide - Samples - Schema - Configuration - Functions - FAQ - API (Javadoc)
|
|
|
|
JasperReports - Functions Sample (version 6.21.0) | |
|
|
|
Main Features in This Sample | |
| Custom Functions in Report Expressions |
|
|
||||
top | |||||
|
|||||
Custom Functions in Report Expressions | Documented by Sanda Zaharia | ||||
|
|||||
| Description / Goal |
| How to use JasperReports built-in functions inside expressions | ||
| Since |
| 5.1.2 | ||
|
|||||
|
Expressions in JasperReports
For most common situations JasperReports expressions represent the perfect tool for acquiring and processing dynamic data. But in some particular cases expressions may also prove their own limitations, especially when series of complex calculations are required to compute a result. In order to avoid writing too long, often unreadable expressions, such calculations can be stored in Java/Groovy methods or Javascript functions. Further, calling a Java method from within an expression requires some specific background in Java programming, regarding imports, object initialization and so on. Similar programming background is expected for Groovy or Javascript expressions. Custom functions, based on Java annotations and JasperReports extensions mechanism, represent a way to both enhance and simplify expressions. Calling custom functions does not require particular programming skills, all we need is to know the function name and its parameters. All other programming stuff (package imports, Java objects, complex algorithms, etc) is processed transparently to produce the expected output. Expressions also become very simple with custom functions: all their content can be replaced by a function call. Functions perform all necessary calculations and return the result you are looking for. Now let's see how to create a custom function and integrate it into the JasperReports library. Creating Custom Functions in JasperReports As based on the JasperReports extensions mechanism, custom functions need an extension point to be enabled first. To do so, in a jasperreports_extension.properties file add the following properties:
Each function class declared in such a property has to be implemented first, in order to become operational. Basically they are common Java classes containing method implementations. Depending on their purpose, methods are allowed to be static and/or non-static. In order to make available non-static methods, a function class must implement the FunctionSupport interface, possibly by extending the built-in AbstractFunctionSupport. Notice that since void methods are useless in an expression, properly implemented function classes should expose methods that provide return types. Functions Annotations Custom function classes are characterized by specific class and method-level annotations. Annotations metadata collected at runtime are used to facilitate the function call mechanism, even in complex i18n environments.
Built-in JasperReports functions are documented here. Next, let's see a step-by-step example of adding custom functions to JasperReports library. The built-in JR functions were created this way and are all available in the net.sf.jasperreports.functions.standard package (under the /src directory in the present sample). Following are the necessary steps
to make functions ready-to-use:
DateTimeCategory.java package net.sf.jasperreports.functions.standard; import net.sf.jasperreports.functions.annotations.FunctionCategory; /** * This class should maintain all function methods that belongs to the category {@link #DATE_TIME}. */ @FunctionCategory( //"DATE_TIME" // if not specified, the value is the name of the category class ) public final class DateTimeCategory { }Notice the @FunctionCategory annotation to ensure it is a function category class.
DateTimeFunctions.java Below is a code fragment extracted from the function class DateTimeFunctions :
package net.sf.jasperreports.functions.standard; // import declarations here // ... /** * This class should maintain all function methods that belongs to the category {@link #DATE_TIME}. */ @FunctionCategories({DateTimeCategory.class}) public final class DateTimeFunctions { private static final Log log = LogFactory.getLog(DateTimeFunctions.class); // ===================== TODAY function ===================== // /** * Returns the current date as date object. */ @Function("TODAY") public static Date TODAY(){ return new Date(); } // other methods declared here // ... // ===================== DAY function ===================== // /** * * Returns the day of a given date. Date object can be a String, long value (milliseconds) or Date instance itself. */ @Function("DAY") @FunctionParameters({ @FunctionParameter("dateObject")}) public static Integer DAY(Object dateObject){ return getCalendarFieldFromDate(dateObject,Calendar.DAY_OF_MONTH); } // ===================== WEEKDAY function ===================== // /** * Returns the day of the week for a given date. Date object can be a String, long value (milliseconds) or Date instance itself. */ @Function("WEEKDAY") @FunctionParameters({ @FunctionParameter("dateObject"), @FunctionParameter("isSundayFirstDay")}) public static Integer WEEKDAY(Object dateObject){ return WEEKDAY(dateObject, false); } public static Integer WEEKDAY(Object dateObject, Boolean isSundayFirstDay){ Integer dayOfWeek = getCalendarFieldFromDate(dateObject,Calendar.DAY_OF_WEEK); if(dayOfWeek==null) { if(log.isDebugEnabled()){ log.debug("Unable to get the correct day of the week."); } return null; } if(isSundayFirstDay){ // By default Sunday is considered first day in Java // Calendar.SUNDAY should be a constant with value 1. // See the Calendar.DAY_OF_WEEK javadoc return dayOfWeek; } else{ // shift the days if(dayOfWeek==Calendar.SUNDAY){ return 7; } else{ return dayOfWeek-1; } } } // other public methods declared here // ... // private methods declared here // ... }Notice the @FunctionCategories({DateTimeCategory.class}) annotation at class level, ensuring that all methods (functions) in this class are
Date/Time functions.
Public methods (excepting the overloaded ones) expose a @Function annotation necessary as function identifier. For overloaded methods the
@Function and other annotations are declared only once, since these methods are sharing the same function name but provide different number
of parameters. An example is given by the WEEKDAY overloaded method.
Also notice how parameters are annotated where they are present: the @FunctionParameters annotation contains an array of @FunctionParameter
that stores the parameter identifier.
I18n and Localization 2 related code fragments are shown below. The first one comes from the default jasperreports_messages.properties file: net.sf.jasperreports.functions.standard.DateTimeCategory.description = Category for date and time manipulation functions net.sf.jasperreports.functions.standard.DateTimeCategory.name = Date & Time net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.dayOfMonth.description = The day of the new date net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.dayOfMonth.name = Day of month net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.description = Creates a date object using the specified information on day, month and year. net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.month.description = The month of the new date net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.month.name = Month net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.name = DATE net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.year.description = The year of the new date net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.year.name = YearThe other one is the Italian translation of this fragment in the jasperreports_messages_it.properties file: net.sf.jasperreports.functions.standard.DateTimeCategory.description = Categoria di funzioni per la manipolazione di date e tempo net.sf.jasperreports.functions.standard.DateTimeCategory.name = Data e tempo net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.dayOfMonth.description = Il giorno della data net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.dayOfMonth.name = Giorno net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.description = Crea una nuova data utilizzando le informazioni di giorno, mese e anno specificati. net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.month.description = Il mese della data net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.month.name = Mese net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.name = DATE net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.year.description = L''anno della data net.sf.jasperreports.functions.standard.DateTimeFunctions.DATE.year.name = AnnoRunning the sample by default, all output texts will result in English. Changing the REPORT_LOCALE to Italian will translate the output texts into Italian.
jasperreports_extension.properties Following is the content of the related jasperreports_extension.properties file:
net.sf.jasperreports.extension.registry.factory.functions=net.sf.jasperreports.functions.FunctionsRegistryFactory net.sf.jasperreports.extension.functions.datetime=net.sf.jasperreports.functions.standard.DateTimeFunctions net.sf.jasperreports.extension.functions.math=net.sf.jasperreports.functions.standard.MathFunctions, net.sf.jasperreports.functions.standard.LogicalFunctions net.sf.jasperreports.extension.functions.text=net.sf.jasperreports.functions.standard.TextFunctionsHere the {registry_id} is assumed to be functions . There are 3 different function classes properties with specific
{property_suffix}-es . Math and logical functions are declared in a comma separated list.
Running the Sample Running the sample requires the Apache Ant library. Make sure that ant is already installed on your system (version 1.5 or later).
In a command prompt/terminal window set the current folder to demo/samples/functions within the JasperReports source project and run the
> ant test command.
It will generate a PDF sample that enumerates all built-in JR functions grouped by categories and, on the last page, some examples of function usage in JasperReports expressions. The generated PDF sample can be found in the demo/samples/functions/build/reports directory.
|
||||
|
|
© 2001- Cloud Software Group, Inc. www.jaspersoft.com |