How to model an Administration Page for a Job

by Michela Frigerio
11,033 views Published on Dec 30, 2015
Job
Applies to: 5.1 or higher
Table of contents

A job is a sequence of operations that has to be executed asynchronously by the application. It's possible to schedule a job at a specific time or interval, which means that jobs can be automatically triggered (scheduled when the application starts). It's also possible to schedule a job at runtime: the user navigation can schedule a new job instance. To get started with Jobs please refer to this article.

 
Schedule Policy Cron Expression
Now NOW
In X Minutes IN_X
Every Day seconds minutes hours * * ?
Every X Seconds 0/X * * * * ?
Every X Minutes 0 0/X * * * ?
Every X Hours 0 0 0/X * * ?
Once a week seconds minutes hours ? * day
Once a month seconds minutes hours day * ?
Once a year seconds minutes hours day month ?
Specific Date seconds minutes hours day month ? year

This article discusses how to model a Job Administration Page for your Web application, in which the user can manage the Job Schedule at runtime, which means while the user is navigating the application. This page lets the user schedule a job or deleting a scheduled one. Let's see which are the steps to follow:

  • Add a Page to the Web Model, named "Job Administration Page"
  • Add an Entry Unit to the page and name it "Schedule Job". To understand which are the fields necessary to the user in order to be able to Schedule a Job, you need to know how the Schedule Job Unit works. The available cases are reported in the table on the right. Considering these cases, let's add Fields to the Entry Unit.
  • Add six Selection Fields ("When" - in which there's the list of all the schedule policy options - "Year","DayInt","Hour","Minutes","Seconds"). Add a Slot both label and output to each field. Add the two last Selection Fields "Day" and "Month".
  • Add three Fields ("Every X Seconds","Every X Hours","In/Every X Minutes") of "Integer" type.
  • Add a Script Unit to the page and name it "Prepare Form". This Script Unit prepares the options for all the selection fields of the Schedule Job form. In order to extract some information such as the day names, the month lists and the years, it uses the Calendar class taking also into consideration the current locale used by the user in order to view the page. For the other information, just build a list with the correct range of numbers. This is the sample code

#output int[] calendarDaysInt, String[] calendarDaysValues, int calendarYears

#output String[] calendarMonths, int[] calendarSeconds, int[] calendarMonthsInt

#output String[] calendarDays, int[] calendarHours, int[] calendarMinutes

#output String[] schedulePolicy



import java.text.DateFormatSymbols

import java.util.Locale

import java.util.Calendar

import com.webratio.rtx.RTXLocalizationService

import com.webratio.rtx.RTXConstants



def userPreferredLocales = localContext

                       .get(RTXConstants.USER_PREFERRED_LOCALES_KEY);

RTXLocalizationService i18nService = rtx.getLocalizationService()

Locale currentLocale = i18nService

                       .getLocale(userPreferredLocales, 

localContext, sessionContext)

DateFormatSymbols symbols = new DateFormatSymbols(currentLocale)

 

Calendar currentDate = Calendar.getInstance(currentLocale)

def schedulePolicy = ["Now","In X Minutes","Every Day","Once a Week",

"Once a Month","Once a Year","Specific Date","Every X Seconds",

"Every X Minutes","Every X Hours"]

def currentYear = currentDate.get(Calendar.YEAR)

def calendarMonths = symbols.getMonths().findAll{it != ""}

def calendarMonthsInt = 1..12 as List

def calendarDays = symbols.getWeekdays().findAll{it != ""}

def calendarDaysValues = symbols.getShortWeekdays()

                       .findAll{it != ""}.collect{it.toUpperCase()}

def calendarYears = currentYear..(currentYear+10) as List

def calendarHours = 0..23 as List

def calendarMinutes = 0..59 as List

def calendarSeconds = 0..59 as List

def calendarDaysInt = 1..31 as List





return ["calendarDaysInt": calendarDaysInt, 

        "calendarDaysValues": calendarDaysValues, 

        "calendarYears": calendarYears, 

        "calendarMonths": calendarMonths, 

        "calendarSeconds": calendarSeconds, 

        "calendarMonthsInt": calendarMonthsInt,

        "calendarDays": calendarDays, 

        "calendarHours": calendarHours, 

        "calendarMinutes": calendarMinutes, 

        "schedulePolicy": schedulePolicy]


  • Connect the Script Unit and the Entry Unit with a transport link and make the coupling just like the figure on the right.
  • Add a Variable named "schedulePolicy" to the page so that you can show to the user different fields, depending on the Schedule Policy choice. In the Properties View choose "String" for the Variable type, choose the Schedule Job Entry Unit for the Unit property and choose the "When" field for the Parameter property.
  • Add a Schedule Job Unit outside the page. In the Properties View, choose "Custom Cron Expression" for the Schedule Policy, then choose a modeled Job. Note that the Administration page allows you to manage the scheduling of one job. If you want to manage different jobs, you have to add an additional Field in the Entry Unit which contains the Job list, and then use a set of Schedule Job Unit, with a Switch Unit preceding them, and choosing wich one of them should be processed.
  • Add a Script Unit outside the page. This unit builds the correct cron expression for each schedule policy chosen by the user and passes it to the Schedule Job Unit. The Groovy script just consider the schedule policy and uses a subset of the input parameter in order to build the cron expression. This is the sample code.

#input String schedulePolicy, int hours, int minutes, int seconds, String day

#input int month, int year, int inMinutes, int dayInt, int inSeconds, int inHour

          

def cronExpression



if("Now".equals(schedulePolicy)){

	cronExpression = "NOW"

} else if ("Every X Seconds".equals(schedulePolicy)) {

    cronExpression = "0/" + inSeconds + " * * * * ?";

}else if ("Every Day".equals(schedulePolicy)) {

    cronExpression = seconds + ' ' + minutes + ' ' + hours + " * * ?"

}else if ("In X Minutes".equals(schedulePolicy)) {

    cronExpression = "IN_" + inMinutes;

} else if ("Every X Minutes".equals(schedulePolicy)) {

    cronExpression = "0 0/" + inMinutes + " * * * ?";

} else if ("Every X Hours".equals(schedulePolicy)) {

    cronExpression = "0 0 0/" + inHours + " * * ?";

} else if ("Once a Week".equals(schedulePolicy)) {

    cronExpression = "" + seconds + ' ' + minutes + ' ' + 

                     hours + " ? * " + day;

} else if ("Once a Month".equals(schedulePolicy)) {

    cronExpression = "" + seconds + ' ' + minutes + ' ' + 

                     hours + ' ' + dayInt + " * ?";

} else if ("Once a Year".equals(schedulePolicy) && month > 0) {

    cronExpression = "" + seconds + ' ' + minutes + ' ' +

                     hours + ' ' + day + ' ' + month + " ?";

} else if ("Specific Date".equals(schedulePolicy) && month > 0) {

    cronExpression = "" + seconds + ' ' + minutes + ' ' + 

                     hours + ' ' + day + ' ' + month + " ? " + year;

} else {

    cronExpression = null;

}



return cronExpression





  • Connect the Entry Unit and the Script Unit with a normal link named "Schedule" and make the coupling just as shown in the following figure.
  • Connect the Script Unit and the Schedule Job Unit with an OK link and couple the "result" output parameter of the Script Unit with the "Cron Expression" input of the Schedult Job Unit.
  • Connect the Schedule Job Unit to the Page with an OK link


The result model should look like the following figure:

   

Let's add the information that let the use understand that the schedule is saved correctly. To do this you must use the "Database" Storage Type for your modeled Jobs. First of all you have to explicitely have in the Data Model the entity storing the Triggers for all jobs.

  • In the main menu choose Window -> Preferences -> WebRatio -> Modeling. Remove the flag, if present, to the "Ignore Quartz tables" property. Click on the Apply button and then on the OK button.
  • Right click on the Database node in the Data Model tab and choose the Synchronize button. Click on the Show Only Incoming elements button and choose the "QrtzJobDetails", "QrtzTriggers" and "QrtzCronTriggers" entities. Choose also the "QrtztriggersQrtzjobdetails" relationship. Import them into the model. Add a new attribute to the "QrtzTriggers" entity, name it "Job Name" and import it from the "QrtzJobDetails" entity. After this operation the Data Model should contain the following entities and attributes
  • In the "Job Administration Page" add an Index Unit on the QrtzCronTriggers entity. Choose the display attributes ("triggerName","triggerGroup","triggerState","cronExpression" and generate the project.
  • Add a Cancel Job Unit outside the page and name it "Delete Schedule".
  • Connect the Index Unit and the Cancel Job Unit with a normal link named "Cancel Schedule". Couple the "Job Name" attribute of the Index Unit with the "Job Instance Identifier" of the Cancel Job Unit.
  • Connect the Cancel Job Unit to the page with an OK link. Look at the following figure for the final version of the Web Model