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 13 - Scheduling of the Designer guide.
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 (<EspressReport-installation-directory>/help/manual/code/src directory), editing the code to enter the new connection information and recompiling the code. If you wish to, you can move the newly compiled code to the <EspressReport-installation-directory>/help/manual/code/classes directory before running it.
4.2.) Connecting to EspressManager
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.
4.2.1.) EspressManager running as application
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:
For example, the following lines of code:
will connect to EspressManager running on someMachine and listening on somePortNumber.
Please note that if 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.
4.2.2.) EspressManager running as servlet
If EspressManager is running as a servlet, you can use the following methods:
For example, the following lines of code:
will connect to EspressManager running at http://someMachine:somePortNumber/EspressReport/servlet.
Please note that these methods exist in the QbScheduler and ScheduleModifier classes.
4.3) Invoking Scheduler Graphical Interface
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:
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:
You can schedule a report to be exported using Scheduler. The following code, given below, shows how to do this:
ScheduleModifier.addScheduleTask(sObj);
Note that any references to a data source, or 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 1 minute.
The examples below show how to set up a periodic schedule:
ScheduleObject sObj = new ScheduleObject("Report_Periodically", ScheduleObject.REPORTOBJ);
sObj.setFileLocation("help/examples/SampleReports/templates/Account.rpt");
String exportLoc = sObj.pickDefaultExportLocation();
sObj.setReportType(IExportConstants.DHTML);
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 5 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("help/manual/code/templates/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("help/manual/code/templates/EmployeeDetails.rpt");
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("help/manual/code/templates/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("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, 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/chart when scheduling an export. Note that atleast 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("help/manual/code/templates/EmployeeDetails.rpt");
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_EmailLink", 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, 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).
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.
4.7.) Getting Details of a Failed Schedule
Sometimes, a schedule 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("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, 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);
4.8.) ICallBackScheduler Interface
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 ServerCommands.txt (in the <EspressReport-installation-directory>/userdb 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 ServerCommands.txt:
-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 ServerCommands.txt:
-ListenerManagerClass:MyEspressReportListenerManager
Make sure that both MyEspressReportListenerManager and MyEspressReportSchedulerListener are in the CLASSPATH.
You can also use the Report Bursting feature in Scheduler 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:
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 doesn't 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 <EspressReport-installation-directory>/help/EspressReportapidocs/index.html.
EspressReport API provides an easy-to-use and powerful API to query the scheduler interface as well as 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.4 or above. The EspressReport API has been tested on Windows, Solaris, Linux, AIX and HP platforms.