This article is old and is being consolidated into the book.
Please refer to the corresponding chapter(s) therein.
If the chapters or sections are not completed yet, you can use this article.
Refer to the examples as they are tested against the latest code.

Table Of Content

  1. Scheduled Activities
    » Monitor and Control
  2. Run Native Executables
  3. Sending E-Mails
  4. SSH and SCP
  5. Summary
  6. Code Listings

Schedule, Execute, E-Mail, SSH, SCP

By James Jianbo Huang    October 2001  UPDATED: Jan 2003     non-printer version

Abstract   The schedule statement schedules one-time or repetitive jobs to run at intervals or at specific moments for any kind of actions. The job also has a built-in HTTP server as a HTML-based control panel, activated when a port number is specified. The code in the job can take and interpret commands from the control panel and/or generate custom information for display. Executables are run with the exec command with all kinds of input/output and piping options, including taking input from the script itself or sending output back to the script for processing; working directory and environment variables can be set. The mail::send statement sends messages in text, HTML or both with or without attachment to multiple "to", "cc" and "bcc" recipients. The texts can be in different character sets. SCP and SSH are used to securely transfer files between remote hosts as well as issue commands on the remote machines. All these applications can be highly useful for scheduled jobs to automate tasks.


 

1. Scheduled Activities

The schedule statement schedules jobs to run in the future. Any actions can be specified, such as database operations, run Java or native executables, sending e-mails, etc. It has a number of modes: one-time or repetitive, absolute or non-absolute, and starting at a specific time or after a delay. A HTTP interface is integrated and started when a port number is provided, so that the job can be monitored or controlled via a browser or any HTTP client program.

schedule [ absolute ] [ ( starting | after ) time_or_delay [ repeating period ] block
[ listen on [ title html_title ] control_block ]

Schedules can not be embedded. A program can have one schedule running at a time. Each schedule is run by a timer called $$timer. It can be accessed in the scheduler code, which has these members: time for the current event being handled, period for the current period, htmlOut is the HTML output stream and cmd is the command sent by the control panel client (most likely a brower) -- the last two are valid only in the control block.

To abort a schedule job, run break schedule;.

The following program emulates a count-down process, where 4 one-time events are run one second apart.

Listing 1. countdown.judo -- one-time event
1: time = date(2001,10,12,19,4,57);
2: schedule starting time { println $$timer.time, ": Three!"; }
3: ++time.second;
4: schedule starting time { println $$timer.time, ": Two!"; }
5: ++time.second;
6: schedule starting time { println $$timer.time, ": One!"; }
7: ++time.second;
8: schedule starting time { println $$timer.time, ": LAUNCH!"; }

This is a simple repetitive motion:

Listing 2. heart_beat.judo -- not-so-accurate repetitive events
1: beats_per_minute = 80;
2:
3: schedule repeat 60000 / beats_per_minute
4: {
5:   println 'puh ... at ', $$timer.time;
6: }

Next, we emulate a coocoo clock that every hour it plays so many "Cukoo" sound. Lines 1 through 4 gets the time for the next hour. Line 7 gets the time for this event, and its hour attribute is used for the number of "Cucoo" sound.

Listing 3. coocoo_clock.judo -- accurate repetitive events
 1: $start = date();
 2: ++$start.hour;
 3: $start.minute = 0;
 4: $start.second = 0;
 5: schedule absolute starting $start repeat 3600000
 6: {
 7:   local time = $$timer.time;
 8:   for $i from 1 to time.hour { print 'Cukoo...'; }
 9:   println;
10: }

Scheduled jobs should run quickly, that is, they should not run longer than the scheduled periods. If they do sometimes and mess up the operation, practical synchronization mechanism should be put in place. For instance, suppose every 5 minutes the job checks the database for unprocessed order data. If it founds some, process them. Sometimes e-commerce site may take so many orders in a short period of time, that within that 5-minute period they can not be all processed. What you can do is, for instance, use a temporary database table; when start processing, set a flag there, and reset it when done; if this flag is set, other jobs will simply bypass. The crux of this solution is, use an operation that is always short than the period to enforce the synchronization.

Monitor and Control

By issuing a listen on clause with a port number, you have the scheduled job start a single-thread HTTP server. A title can be specified for the HTML output. If not, the default title is "JudoScript Scheduler Control Panel".

Listing 4. changing_time.judo
 1: history = linkedList{};
 2:
 3: schedule repeat 2000
 4: {
 5:   history.add($$timer.time);
 6:   if $history.length() > 10 { history.remove(0); }
 7: }
 8: listen on 3333 title '<h1>Changing Time</h1>'
 9: {
10:   println <$$timer.htmlOut> '<h3>Latest Events</h3>';
11:   for x in history backward { println <$$timer.htmlOut> x, '<br>'; }
12: }

The job itself does nothing but keeping the execution time in a list for the last 10 events (line 6). Its control panel server listens on port 3333. The control panel is typically run from a browser. The title, "Changing Time", is issued on line 8. The screen is standard above the horizontal line. If and only if both boxes are checked will the job be stopped and closed. Anything user type in to the edit box is sent to the server and becomes the content of $$timer.cmd. What it means is totally up to your interpretation, such as a mini command system. In the control panel code, we used $$timer.htmlOut to write out custom content that shows below the horizontal line (lines 10 and 11).

Review Questions

  • How to schedule a one-time event? How about repetitive events?
  • How to schedule events that happen precisely (up to JVM precision) every 5 minutes?
  • How to obtain the time for the current event and the period for this job?
  • Specified a listen on 4444 for a scheduled job with an empty control block. When connected to it via a browser, what will you see?
  • Think of a scheduled job with the control panel, and devise an interactive mechanism that takes the command from the control panel in the brower and acts upon it.

 

»»» Top |  This Section «««

 

2. Sending E-Mails

You can send e-mails directly from JudoScript. To use the e-mail feature, you need to have the javax.mail packages in the class path. It can be obtained from various places, such as the "j2ee.jar" file in the J2EE installation. Before sending any messages, you must first connect to a mail server by calling the system function:

mail::connect( server [ , username [ , password ] ] );
mail::disconnect();
The server may include a port number, separated by a colon. Once connected, you can easily send one, two, fitfy or a million e-mails from a simple JudoScript script; spamming is never easier. Well, if one does want to spam, there are zillions of ways anyway.

The syntax for sending mail is:

mail::send [ charset ]
( ( from | to | cc | bcc | attach | subject | body | htmlBody ) : content )+
As you see, text and/or HTML messages can be sent at the same time. You can specify character sets for addresses, subject and bodies. If charset is set to mail::send, both the text and HTML bodies will use it. A charset can have "charest=". The following two examples are equivalent:
  mail::send 'iso-2022-jp' ...
  mail::send 'charset=iso-2022-jp' ...
Alternatively, you can call the system function setCharset() to set the language character set for the whole language environment. The mail::send command uses that if no charset is explicitly specified in itself. This global character set may affect text encoding used in other places.

Files can be attached; messages can be sent to a list of "to", "cc" and/or "bcc" recipients; within each list, recipients are separated by commas. Each clause can appear at most once. For the message bodies, the here-doc is a big convenience. Here is an example:

mail::send
   from: 'syang@exotic.nat'
     to: 'foodback@judoscript.com, syang56@yahoo.cum'
subject: 'bug report'
   body: [[*
         Hi there,

         JudoScript is cool. I'm doing a lot and will do a lot more
         with it.

         I think I've found a bug. I have a program, 'tvcontrol.judo';
         there is a function like this:

           function switchTV $on {
             if $on { turnOnTV(); } else { turnOffTV(); }
           }

         however, when it is called with $on=3, it turns off my VCR!
         I believe this is a bug in JudoScript that, when the value
         is not 0 or 1, it emits erroneous radio shock waves that
         affect other appliances than the intended one. Please take
         a look. Thank you!

         Best regards,
         -- Steve Young
         *]];
The following example sends out trial software to newly registered users, whose information is stored in a database. For each user with status "NEW", a zip file and a "readme.txt" file are sent, and his/her status is changed to "TRIAL VERSION" in the database. This program is likely executed by a scheduled job that runs at midnight or later.
db::connect 'jdbc:oracle:thin:@localhost:1521:userdb', 'onlyme', 'uggess';

db::query u:
  select email, lastname, solute from usertbl where status='NEW';

db::prepare: update userdb set status='TRIAL VERSION' where email=?;
while u.next() {
  sendSoftware(u.email, u.lastname, u.solute);
  executeUpdate with @1 = u.email;
}

db::disconnect;

function sendSoftware email, lname, solute
{
  mail::send
     from: 'info@judoscript.com'
       to: email
  subject: 'The software. Thank you!'
   attach: 'readme.txt, software.zip'
     body: [[*
           Dear (* solute *) (* lname *),

           Thank you very much for your interest in this software.
           Attached is a zip file for the software and a readme
           text file. Follow the instructions therein for
           installation and using. Enjoy!

           Please visit www.judoscript.com for the latest news
           and information. Thank you!

           Sincerely,
           JudoScript
           *]]
 htmlBody: [[*
           <html><body>
           <p>Dear (* solute *) (* lname *),

           <p>Thank you very much for your interest in <i>this software</i>.
           Attached is a <u>zip file</u> for the software and a <u>readme
           text</u> file. Follow the instructions therein for installation
           and using. Enjoy!

           <p>Please visit <a href=www.judoscript.com>www.judoscript.com</a>
           for the latest news and information. Thank you!

           <p>Sincerely,
           <p>JudoScript
           </body></html>
           *]]
  ;
}

Review Questions

  • How to connect to a mail server?
  • Can you send an e-mail message in both text and HTML?
  • Can you have multiple "to" clauses? How to specify multiple recipients?
  • How to attach 3 files to a message?

 

»»» Top |  This Section «««

 

3. SSH and SCP

The SSH and SCP features uses ISNetworks' distribution of MindTerm package, a GPL'ed open-source pure Java SSH/SCP bundle. It is a GUI program that you can use daily; its SCP screen looks like a FTP GUI client. Very handy! Download it from ISNetworks. Make sure the version is "version 1.2.1 SCP release 3" or up. Unpack and put the class jar file into your classpath, and run

%java mindbright.application.MindTerm
If it is the first time use, it prompts you for host, user and password, and generates necessary keys automatically. You should run it to establish such environment before using JudoScript's SSH/SCP features. By the way, the nice SCP screen is available on its "File" menu, not so obvious to the first-time users.

Once the jar file is in the classpath and you have set up the environment, please refer to the language spec for how to use. It is rather straightforward.

 

»»» Top |  This Section «««

 

4. Summary

Running scheduled jobs is an important application of scripting languages. The schedule command allows to schedule one-time jobs or repetitive ones, running at intervals or at specific moments. The actions for the job can be any valid JudoScript statements and commands except for another schedule, that is, no embedded schedules. The internal variable, $$timer, has members like time and period for code to access. A JudoScript scheduled job has a built-in HTTP server for control panel. All you have to do is specify the listen on with a port number, and use a browser to see the current status. The control panel allows administrators to stop the job, or send a command string to it, which becomes $$timer.cmd in the script that you can respond to. With $$timer.htmlOut, you can generate more information to the control panel.

Scheduled jobs typically check database or some files for changes and respond by processing the data, running other applications, handling files and archives and sending results either via remote calls to systems or e-mails to humans. JudoScript has flexible JDBC scripting, running executables, invoking Java programs and sending e-mails. So practically you rarelly have to leave JudoScript.

The exec command can run executables as flexible as any shells or Windows consoles with input/output redirections, merging program output and error, and piping output to other executables; what is more, the command line can even take input from the script, or pipe the output back to the script for processing. A command line can be indicated to take from the system input; if it is not indicated and the program reads system input, an EOF is sent immediately so it does not hang the script.

E-mails can be sent directly via the mail::send command; the message can be in text, HTML or both. File attachment is supported, so are multiple recipients for "to", "cc" and "bcc". Prior to sending e-mails, a mail server must be connected via mail::connect() system call. The Java extension packages of javax.mail must be present.

 

»»» Top |  This Section «««

 

5. Code Listings

  1. countdown.judo -- one-time event
  2. heart_beat.judo -- not-so-accurate repetitive events
  3. coocoo_clock.judo -- accurate repetitive events
  4. changing_time.judo


Copyright c 2001-2021 JudoScript.COM. All Rights Reserved.