EspressReport has a Scheduler interface through which reports can be exported at a specific time or specific intervals. This allows EspressReport to handle mundane tasks such as exporting reports than having a user log in at a specific time and explicitly perform the operation. For more information on how to use Scheduler, please see Section 1.13 - Scheduling.
When writing Scheduler API code, two main classes are used; ScheduleObject
, which is used to give details on the schedule job, and ScheduleModifier
, which is used to alter Scheduler.
Both ReportAPIWithChart.jar
and Scheduler.jar
(in the EspressReport/lib
directory) need to be added to the CLASSPATH
for any code using the Scheduler.
All examples and code given in the manual assume that EspressManager is running locally (i.e., on your local machine) and default port number (22071). You can change this by going to the source code (you can download the source code by clicking on the Full Source Code link in the corresponding chapter), editing the code to enter the new connection information and recompiling the code.
You cannot run Scheduler (or any Scheduler code) without connecting to EspressManager first. Depending on whether EspressManager is running as an application or a servlet, you can use API methods to specify connection information.
If EspressManager is running as an application, you can use API methods to specify the IP address/machine name where EspressManager is located and the port number EspressManager is listening on.
You use the following two API methods to set the connection information:
static void setServerAddress(java.lang.String address); static void setServerPortNumber(int port);
For example, the following lines of code:
QbScheduler.setServerAddress("someMachine"); QbScheduler.setServerPortNumber(somePortNumber);
will connect to EspressManager running on someMachine
and listening on somePortNumber
.
Please note that if the EspressManager connection information is not specified, the code will attempt to connect to EspressManager on the local machine and listening to the default port number (22071).
Please note that these methods exist in the QbScheduler
and ScheduleModifier
classes.
If EspressManager is running as a servlet, you can use the following methods:
public static void useServlet(boolean b); public static void setServletRunner(String comm_URL); public static void setServletContext(String context);
For example, the following lines of code:
QbScheduler.useServlet(true); QbScheduler.setServletRunner("http://someMachine:somePortNumber"); QbScheduler.setServletContext("EspressReport/servlet");
will connect to EspressManager running at http://someMachine:somePortNumber/EspressReport/servlet
.
Please note that these methods exist in the QbScheduler
and ScheduleModifier
classes.
Scheduler can be called from Report API in either an application or an applet. The following example, which can run as an applet or application, invokes Scheduler by constructing a QbScheduler
Object:
QbScheduler qbScheduler = new QbScheduler((Applet)null, frame);
((JPanel)frame.getContentPane()).add("Center", qbScheduler.getScheduler());
frame.pack();
frame.setVisible(true);
A few “set” methods are also available if the programmer wishes to configure the Scheduler Interface to open with specific features turned on or off. Here are two methods that can be used to set the root directory for browsing and to set the insert command
feature on of off:
qbScheduler.setRootDirectoryForBrowse(String root);
qbScheduler.setInsertCommandEnabled(boolean state);
You can schedule a report to be exported using Scheduler. The following code, given below, shows how to do this:
ScheduleObject sObj = new ScheduleObject("Report_OneTime", ScheduleObject.REPORTOBJ); sObj.setFileLocation("help/manual/code/templates/Account.rpt"); sObj.setReportType(IExportConstants.DHTML); sObj.setTaskOption(ScheduleObject.ONE_TIME); String exportLocation = sObj.pickDefaultExportLocation(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 1); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(false); ScheduleModifier.addScheduleTask(sObj);
Note that any references to a data source or to a report file using the relative URL reference (e.g. help/manual/code/templates/Account.rpt
) are relative to the directory from where EspressManager is running in.
The above code schedules a report (Account.rpt) to be exported to DHTML, in the default export directory and sets the export to take place once and in one minute.
The examples below show how to set up a periodic schedule:
sObj.setFileLocation("Account.rpt"); sObj.setReportType(IExportConstants.DHTML); String exportLoc = sObj.pickDefaultExportLocation(); sObj.setTaskOption(ScheduleObject.TIME_INTERVAL); /*** every 5 mins ****/ sObj.setIntervalType(ScheduleObject.TIME); sObj.setTimeInterval(5); // export every 5 mins /*** every day ****/ // sObj.setIntervalType(ScheduleObject.DAYS); // sObj.setDayInterval(1); // export everyday Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 5); sObj.setStartDate(calendar.getTimeInMillis()); Calendar calendar2 = Calendar.getInstance(); calendar2.add(Calendar.MINUTE, 26); sObj.setEndDate(calendar2.getTimeInMillis()); sObj.setSendEmail(false); ScheduleModifier.addScheduleTask(sObj);
The above code snippet shows how to schedule a job to run every five minutes (or every day, depending on which section of the code you comment).
The following code snippet shows to schedule a job to run at certain time periods:
ScheduleObject sObj = new ScheduleObject("Report_Time", ScheduleObject.REPORTOBJ); sObj.setFileLocation("Account.rpt"); String exportLoc = sObj.pickDefaultExportLocation(); sObj.setReportType(IExportConstants.PDF); sObj.setTaskOption(ScheduleObject.FIXED_DAYS); /*** export every 2 hrs. monday through friday ****/ sObj.setSpecifyDays(new int[] { 1, 2, 3, 4, 5 }); sObj.setStartTime(9 * 60); // 9:00AM in minutes sObj.setEndTime(22 * 60); // 10:00PM in minutes sObj.setTimeInterval(2 * 60); // export every 2 hours /*** export at specific times on specific dates ***/ // sObj.setSpecifyDates(new int[]{26,27,28,29}); // export on specific dates // sObj.setSpecifyTime(new int[]{16 * 60, 17 * 60, 18 * 60}); // 4PM, 5PM and 6PM in minute Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 5); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setEndDate(-1); // run indefinitely sObj.setSendEmail(false); ScheduleModifier.addScheduleTask(sObj);
You can also specify the parameters when scheduling a parameterized chart or report to be exported. The following code shows how:
ScheduleObject sObj = new ScheduleObject("ParamReport_OneTime", ScheduleObject.REPORTOBJ); // Single Param Report sObj.setFileLocation("EmployeeDetails.pak"); String exportLoc = sObj.pickDefaultExportLocation(); sObj.setReportType(IExportConstants.DHTML); sObj.setTaskOption(ScheduleObject.ONE_TIME); // 1st param set {"Denise Carron"} Object tmp1[] = { "Denise Carron" }; // 2st param set {"Frank Carnody"} Object tmp2[] = { "Frank Carnody" }; Vector paramList = new Vector(); paramList.addElement(tmp1); paramList.addElement(tmp2); sObj.setParamList(paramList); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 5); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(false); ScheduleModifier.addScheduleTask(sObj);
A security level for the report can also be specified. The following code shows how to specify a security level (for report cells and/or query parameters):
ScheduleObject sObj = new ScheduleObject("Report_Security", ScheduleObject.REPORTOBJ); sObj.setFileLocation("OrderFormByRegion.rpt"); sObj.setReportType(IExportConstants.DHTML); sObj.setTaskOption(ScheduleObject.ONE_TIME); sObj.setSecurityLevel("ParamSet"); String exportLocation = sObj.pickDefaultExportLocation(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 10); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(false); ScheduleModifier.addScheduleTask(sObj);
You can also specify the schedules to be sent to one or more email addresses, either as a link or an attachment. The following code shows how to send a scheduled job which contains a non-parameterized report to multiple recipients:
ScheduleObject sObj = new ScheduleObject("Report_Email", ScheduleObject.REPORTOBJ); sObj.setFileLocation("Account.rpt"); sObj.setReportType(IExportConstants.DHTML); sObj.setTaskOption(ScheduleObject.ONE_TIME); String exportLocation = sObj.pickDefaultExportLocation(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 10); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(true); sObj.setFromAddress("user1@quadbase.com"); sObj.setSubject("Report Email Account Report"); sObj.setBodyText("Scheduled Export of Account from user1"); sObj.setEmailType(ScheduleObject.ASATTACHMENT); sObj.setToAddresses(new String[] { "user2@quadbase.com", "user3@quadbase.com" }); ScheduleModifier.addScheduleTask(sObj);
Similarly, emails can be sent for each parameter set chosen for a parameterized report or chart when scheduling an export. Note that at least one email address must be specified for each parameter set and the same recipient can be used for multiple parameter sets.
ScheduleObject sObj = new ScheduleObject("ParamReport_Email", ScheduleObject.REPORTOBJ); // Single Param Report sObj.setFileLocation("EmployeeDetails.pak"); String exportLoc = sObj.pickDefaultExportLocation(); sObj.setReportType(IExportConstants.DHTML); sObj.setTaskOption(ScheduleObject.ONE_TIME); // 1st param set {"Denise Carron"} Object tmp1[] = { "Denise Carron" }; // 2nd param set {"Frank Carnody"} Object tmp2[] = { "Frank Carnody" }; Vector paramList = new Vector(); paramList.addElement(tmp1); paramList.addElement(tmp2); sObj.setParamList(paramList); Vector paramNameList = new Vector(); paramNameList.addElement("Denise"); paramNameList.addElement("Frank"); sObj.setParamList(paramNameList, paramList); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 5); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(true); sObj.setFromAddress("user1@quadbase.com"); sObj.setSubject("Param Report Email Account Report"); sObj.setBodyText("Scheduled Export of Employee Details from user1"); sObj.setEmailType(ScheduleObject.ASATTACHMENT); Hashtable toAddr = new Hashtable(); toAddr.put("Denise", new String[] { "user2@quadbase.com" }); toAddr.put("Frank", new String[] { "user3@quadbase.com" }); sObj.setParamAddresses(toAddr); ScheduleModifier.addScheduleTask(sObj);
The scheduled reports can also be stored in a web-accessible location and the URL sent via email to various recipients. The following code shows how:
ScheduleObject sObj = new ScheduleObject("Report_Email", ScheduleObject.REPORTOBJ); sObj.setFileLocation("Account.rpt"); sObj.setReportType(IExportConstants.DHTML); sObj.setTaskOption(ScheduleObject.ONE_TIME); String exportLocation = sObj.pickDefaultExportLocation(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 10); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(true); sObj.setFromAddress("user1@quadbase.com"); sObj.setSubject("Report Email Account Report"); sObj.setBodyText("Scheduled Export of Account from user1"); sObj.setEmailType(ScheduleObject.ASLINK); sObj.setURLMapping("http://someMachine:somePort/ScheduledReports/"); sObj.setToAddresses(new String[] { "user2@quadbase.com", "user3@quadbase.com" }); ScheduleModifier.addScheduleTask(sObj);
In addition to scheduling exports, you can also schedule commands to be run at a specific time (or time interval). The code remains the same as the one for scheduling exports except the command to be executed is specified (rather than the report location, export format and export location).
ScheduleObject sObj = new ScheduleObject("Command_OneTime", ScheduleObject.COMMANDOBJ); // Note that someClass does not exist sObj.setCommand("java someClass"); sObj.setTaskOption(ScheduleObject.ONE_TIME); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 5); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(false); ScheduleModifier.addScheduleTask(sObj);
In addition to adding schedules, you can also use the API to remove any schedules. This is done by getting a list of all the jobs scheduled and then delete a particular job.
The following code shows how to delete a particular job:
Vector schedList = ScheduleModifier.getScheduler().getScheduleList();
ScheduleObject obj = (ScheduleObject)schedList.elementAt(0);
ScheduleModifier.removeScheduleTask(obj);
Note that the above code removes the first job in the schedule list. The job may not be visible if it has been already marked for deletion. The recommended approach is to go through the vector and search each ScheduleObject
by the name and then deleting the correct one.
Sometimes, a scheduled job may fail for some reason or another. EspressManager keeps a track of all the failed jobs so that its details can be obtained later. The following code shows how to obtain the details:
Vector vec = ScheduleLog.getFailedScheduledJob(); for (int i = 0; i < vec.size(); i++) { FailedScheduledJob obj = (FailedScheduledJob) vec.elementAt(i); System.out.println("FAIL # " + i + ": Name = " + obj.getScheduledJobName()); System.out.println("File Location = " + obj.getFileLocation()); System.out.println("Time = " + obj.getExportTime()); System.out.println("StackTrace = " + obj.getStackTrace()); }
You can also set up an email to be sent in case the schedule fails. The following code illustrates how:
ScheduleObject sObj = new ScheduleObject("Report_FailedEmail", ScheduleObject.REPORTOBJ); sObj.setFileLocation("Account.rpt"); sObj.setReportType(IExportConstants.DHTML); sObj.setTaskOption(ScheduleObject.ONE_TIME); String exportLocation = sObj.pickDefaultExportLocation(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 10); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(true); sObj.setFromAddress("user1@quadbase.com"); sObj.setSubject("Report Email Account Report"); sObj.setBodyText("Scheduled Export of Account from user1"); sObj.setEmailType(ScheduleObject.ASATTACHMENT); sObj.setToAddresses(new String[] { "user2@quadbase.com", "user3@quadbase.com" }); sObj.setFailSubject("Report_FailedEmail schedule failed"); sObj.setFailBodyText("Cannot send Account report from Report_FailedEmail"); sObj.setFailToAddress("user1@quadbase.com"); ScheduleModifier.addScheduleTask(sObj);
You can also create additional code that performs certain actions based on the Scheduler performing a job (whether successful or not). This code implements the ICallBackScheduler
interface and specifies what to do when a job has been successfully completed or not.
Please note that after creating the code you need to change EspressManager.bat/.sh
(in the <EspressReport-installation-directory>
directory) and add the following:
-SchedulerCallBackClass:<name of class file implementing ICallBackScheduler>
The following code shows how to use the ICallBackScheduler
interface:
import quadbase.scheduler.ICallBackScheduler; import quadbase.scheduler.ScheduleObject; public class CallBackScheduler implements ICallBackScheduler { public CallBackScheduler() {}; public void exportSucceeded(ScheduleObject obj, String path) { System.out.println(obj.getName() + "- EXPORT SUCCEEDED"); System.out.println("PATH = " + path); } public void exportFailed(ScheduleObject obj, String path, Throwable e) { System.out.println(obj.getName() + "- EXPORT FAILED"); System.out.println("PATH = " + path); System.out.println("ERROR = " + e.toString()); } }
To use the above code, add the following to EspressManager.bat/.sh
:
-SchedulerCallbackClass:CallBackScheduler
Make sure that CallBackScheduler
is in the CLASSPATH
. The code will then print messages at the end of each job saying whether the job was run successfully or not.
EspressReport allows scheduled reports to be modified via custom code using server extensions. These custom classes will intercept reports before they are exported and allow users to implement additional business logic to the scheduling process.
To use the Scheduler Listener, you will have to write your own custom class that implements SchedulerListener
. Given below is an example:
import quadbase.reportdesigner.ReportAPI.QbReport; import quadbase.scheduler.ScheduleObject; import quadbase.ext.SchedulerListener; public class MyEspressReportSchedulerListener implements SchedulerListener { public QbReport modifyBeforeExport(QbReport report, ScheduleObject so, String exportPath) { System.out.println("modifyBeforeExport(" + report + "," + so + "," + exportPath + ")"); return report; } }
The above example prints a simple System.out.println
statement before exporting either the report.
To use any custom class implementing SchedulerListener
, you will have to implement another custom class implementing DefaultListenerManager
. For example:
import quadbase.ext.DefaultListenerManager; import quadbase.ext.SchedulerListener; public class MyEspressReportListenerManager extends DefaultListenerManager { public MyEspressReportListenerManager() {} public EspressReportSchedulerListener getSchedulerListener() { return new MyEspressReportSchedulerListener(); } }
To use the above code, add the following to EspressManager.bat/.sh
:
-ListenerManagerClass:MyEspressReportListenerManager
Make sure that both MyEspressReportListenerManager
and MyEspressReportSchedulerListener
are in the CLASSPATH
.
You can also use the Report Bursting feature in the Scheduler by using the API. Note that the report must use a database as the datasource and must be grouped in order for the report to be bursted.
Given below is an example on how to use report bursting:
ScheduleObject sObj = new ScheduleObject("ReportBursting_All", ScheduleObject.REPORTOBJ); sObj.setFileLocation("InventoryInformation.rpt"); String exportLoc = sObj.pickDefaultExportLocation(); sObj.setReportType(IExportConstants.DHTML); sObj.setTaskOption(ScheduleObject.ONE_TIME); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 5); sObj.setStartDate(calendar.getTimeInMillis()); sObj.setSendEmail(true); sObj.setFromAddress("user1@quadbase.com"); sObj.setSubject("Test report bursting"); sObj.setBodyText("You should find a report of one group"); sObj.setEmailType(ScheduleObject.ASATTACHMENT); // export every group as a single report and email using report column values sObj.setBurstReport(ScheduleObject.ALLBURSTING); // get email address from 16th column in template sObj.setEmailColumnIndex(16); ScheduleModifier.addScheduleTask(sObj);
The above code bursts all groups and sends out an email using a report column as the source for the addresses.
Note that in the above code, column 16 does not exist in the template. The method is provided in the example to show how to pass in the email column for bursting.
Javadoc for the entire API is provided along with EspressReport. It is located at Quadbase website.
EspressReport API provides an easy-to-use and powerful API to query the Scheduler interface, as well as to add and remove schedules. You can also write code to perform your own action when a job has been completed successfully (or not) in Scheduler.
Please note that the API requires a JDK 1.8 or above. The EspressReport API has been tested on Windows, Solaris, Linux, AIX, and HP platforms.