JDBC scripting, Part 2

Programming and Java scripting in JudoScript

In Part 1 of this series, I introduced JudoScript, detailed its JDBC (Java Database Connectivity) scripting abilities, and demonstrated the power of its synergy of functional support on top of a general programming language engine. JudoScript is, in a way, a shell for the underlying Java platform, which is, in turn, an interface to today's computing environment that is much richer than 20 or even 10 years ago. JudoScript is designed for today's computing needs, and is a language designed for any computer developer, not just Java developers, to manipulate computers and information.

In Part 2, I concisely present the other face of JudoScript, that is, its programming capability, including Java scripting. I list JudoScript's major features, but do not elaborate on them. The features introduced are all used in a J2EE case study. To conclude, I summarize the differences between conventional and functional scripting languages. I use criteria like signal/noise ratio, directness, coherency, and focus to compare code written in JudoScript with languages like Java and Perl, where Java is arguably one of the best general-purpose programming languages and Perl is the conventional scripting language that no other has surpassed in terms of capability.

Read the whole series on JDBC scripting:

Introduction to programming in JudoScript

The world already has too many programming languages. Inventing a new syntax for programming truly demands reasons. JudoScript, being a general-purpose programming language as well, simply adopts a JavaScript-like programming model and syntax, which is not bad at all. However, JudoScript has many sophisticated datastructures, thread programming, object-oriented programming, and syntactic sugar—it is a powerful programming language. JudoScript is also a top-of-the-line Java scripting language, capable of scripting Java to the fullest allowed by JVMs, including capabilities to extend Java classes and implement Java interfaces using JudoScript classes. I start by introducing the basics of JudoScript programming.

Values in JudoScript all have types. JudoScript has primitive types of integer, double, string, and date and time; all other values are objects, which can be built-in type objects or any Java object. JudoScript is a dynamically typed language, meaning that variables are generic "containers," and the value held in a variable at any time has a definitive type. JudoScript supports object-oriented programming, so you can define your own classes of objects. Each type, whether a primitive value, built-in datastructure, or extraneous object, has numerous properties and a set of predefined methods that are accessed and invoked in the same way regardless of type. Here are some examples:

a = 12345;
println a, ', HEX: ', a.fmtHex(), ', Roman: ', a.fmtRoman();
d = Date(2004, 3, 26);
println 'Today (', d.fmtDate('yyyy-MM-dd'), '), week of the year is ',
d.weekOfYear;
lst = new java::ArrayList;
println "List's length: ", lst.size();

Flow controls include if-elif-else, switch-case-default, while, do-while, and the for-family statements. Unlike Java, the conditional expression for if and while does not have to be quoted in parentheses, but curly braces ({}) must always surround the bodies, even if the body contains just one statement.

Functions and user classes can be defined. I don't discuss class definition in this article. Functions can take parameters; when called, the number of parameters can be less or more than the number of declared parameters. Missing parameters are assumed undefined, and extras are stored in the predefined local array variable, $$args. Functions are always expected to return a value; if no explicit return is used, undefined returns.

Exceptions can be thrown and caught like this:

{ connect to 'fail it', 'any', 'any';
catch:
  println $_; // $_ is the exception object thrown.
finally:
  println 'Finally!';
}

Or, you can use this format:

try {
  connect to 'fail it', 'any', 'any';
} catch ex { // If ex is not specified, $_ is used.
  println ex;
} finally {
  println 'Finally!';
}

Next, let's dig a little deeper by looking at some of JudoScript's built-in data types.

Built-in data types

JudoScript's built-in data types include primitive values; the Array, LinkedList, Set, Object, and TableData objects; and the for..in and printTable statements.

The primitive values

JudoScript's built-in data types include primitive types and datastructures. Primitive types are integer, floating-point number, string, and date and time. All types share many methods; some methods are number-, string-, or date-time-specific. Most number-specific methods are mathematical functions, conversions (e.g., int()), and formats (e.g., fmtHex(), and fmtRoman()). The string value is the most commonly used; it has all the string operations. Moreover, it represents file paths and URLs, so methods exist for those operations, such as fileExists(), fileTime(), isDir(), and parseUrl(). The date/time value has additional methods such as formatDate(). The date/time value also has fields; some are read-only, others are read-write. The following example gets a Date object for tomorrow:

t = Date(); // Now
++t.date;
println t.fmtDate('yyyy-MM-dd');

The fmtDate() (or formatDate()) method takes the same formatting string as the java.text.SimpleDateFormat class. For a variable holding a date or time string, you can call parseDate():

s = '2003-9-18';
t = s.parseDate('yyyy-MM-dd');
println t.fmtDate('MMM d, yy'); // Prints: Sep 18, 03

I discuss some of the detailed usages of primitive types later. Please refer to the language reference for more details.

The Array, LinkedList, and Set objects

Array can be created in two ways, both consistent with JavaScript syntax:

a = [];
a = [ 1, 'xyz', Date() ];
a = new Array;
a = new Array( 1, 'xyz', Date() );

JudoScript arrays are all dynamic, i.e., you can call an array's add() method to add elements. Array elements can be retrieved and set with the [] operator; the index starts at 0.

LinkedLists behave the same as arrays, except the underlying implementation uses linked lists.

Another similar datastructure is the Set object. It can also be created in two ways:

a = LinkedList[];
a = LinkedList[ 1, 'xyz', Date() ];
a = new LinkedList;
a = new LinkedList( 1, 'xyz', Date() );
a = Set[];
a = Set[ 1, 'xyz', Date() ];
a = new Set;
a = Set( 1, 'xyz', Date() );

Sets do not support access by index.

The for..in statement

The for..in statement iterates many JudoScript and Java datastructures, including arrays, linked lists, sets, Java arrays, and instances of these Java classes/interfaces: java.util.Iterator, java.util.Enumeration, java.util.Collection, java.util.List, and java.util.Map. All JudoScript loops support an intrinsic function, loopIndex(), which can prove useful at times. The following example prints an array's elements as a CSV (character-separated value):

a = [ 1, 'xyz', Date() ];
for x in a {
  if loopIndex() > 0 { print '\t'; }
  print x;
}
println;

Arrays (including LinkedList) have practical methods. You can sort, filter, and convert an array flexibly, with user-defined comparison, filtering, and transformation function objects.

The Object object

Object is compatible with the name-sake JavaScript object and is the parent of any user-defined class. It is a map that stores name-value pairs. An Object can be created in two ways:

a = {};
a = { city='San Jose', state='CA' };
a = new Object;
a = new Object( city='San Jose', state='CA' );

Values can be accessed via names or expressions:

a = new Object;
a.city  = 'San Jose';
a.state = 'CA';
println 'City:  ', a.city;
x = 'state';
println 'State: ', a.(x);

Object has many methods, some of which are quite powerful, such as keys(), keysSorted(), keysSortedByValues(), keysFiltered(), and keysFilteredByValues().

The TableData object and the printTable statement

A TableData object is a 2D array with a title. The title is an array of strings. A row number references each row; within a row, the value can be referenced by either the column index or the column name. You can sort or filter the rows based on a specific column or columns, and, of course, you can get or set individual cells. TableData has a special print statement, printTable.

The example of the tableDesc() function presented in Part 1 demonstrates the use of printTable well; the code is repeated here:

function tableDesc tableName, dbcon {
  if dbcon == null { dbcon = $$con; }
  executeQuery qry use dbcon:
     SELECT * FROM (* tableName *) WHERE 0 > 1
  ;
  println [[*
    ----------------------------------------------------------------------
    Name            Type       Display  Precision   Scale Nullable Class
                    Name          Size                             Name
    ----------------------------------------------------------------------
  *]];
  printTable qry.getColumnAttributes()
         for column('name')               :<16,
             column('type')               :<10,
             column('displaySize')        :>8,
             column('precision')          :>11,
             column('scale')              :>8,
             column('nullable').fmtBool() :>9,
             ' ', column('className'), nl; // Newline
}
// Try it out
connect to dbUrl, dbUser, dbPassword;
tableDesc 'emp';
disconnect();

The qry.getColumnAttributes() call returns a TableData, which has columns like name, type, and scale. The column() expression in that statement denotes a value for this column. The :<16 is a print alignment expression (meaning left-aligned, width of 16).

As you can see, JudoScript uses the JavaScript syntax and programming model, but is much more powerful than JavaScript. If you deem algorithmic programming as a domain, then JudoScript also supplies rich domain support for programming just like JDBC scripting and other functional domain support. There are many interesting topics and details I can't afford to go into in this article; please refer to the language reference and other resources to learn more. Next I tackle another important programming topic, Java scripting.

Java scripting

JudoScript can create and use Java objects, arrays, and class objects. Java objects and arrays are created with the same new operator but in a special namespace called java. To access a Java class, use the java:: operator:

a = new java::java.awt.Dimension(20,30);
a = new java::int[4];
a = new java::int[] { 1, 2, 3, 4 };
c = java::java.sql.Types;
println c.BOOLEAN;
(java::System).out.println('aaa');

JudoScript supports the same Java import statement for easier resolution of Java class names. The java.lang.*, java.io.*, and java.util.* packages are implicitly imported. Thus, we could use System and Class directly in the previous example.

Java arrays and java.util.List instances share operations with JudoScript arrays:

a = new java::int[] { 1, 2, 3, 4 };
for x in a {
  println 'a[', loopIndex(), '] = ', x;
}
a = new java::Vector;
a[0] = 'A';
a[9] = 'J';
for x in a {
  println 'a[', loopIndex(), '] = ', x;
}

JudoScript also supports extending Java classes and implementing Java interfaces. The following is an example:

class MySetIterator extends java::HashSet, Iterator
{
  Iterator iter;
  constructor a, b, c {
    super();
    iter = null;
    if c != null { add(c); }
    if b != null { add(b); }
    if a != null { add(a); }
  }
  // Iterator methods
  boolean hasNext() {
    if iter == null {
      iter = iterator(); // of HashSet.
    }
    return iter.hasNext();
  }
  Object next() {
    return (iter==null) ? null : iter.next();
  }
}
o = new MySetIterator('Hi!', 9);
o.add('abc');
o.add(Date(2004,7,4));
for x in o { println x; }

This class looks a bit odd: it is somewhat like a Java class and somewhat like a JudoScript class. In fact, this is a dynamically generated Java class with fields (e.g., iter) and methods (e.g., hasNext() and next()). Fields and methods in such classes are always public. The constructor and the method bodies are JudoScript code, and the new operator creates new instances. More rules govern such classes; please refer to Resources to learn more.

Useful mechanisms for data processing

Now let's look at some of the JudoScript mechanisms that will help you process data.

The print statements

JudoScript has println, print, and flush statements. All three can take any number of parameters and print to System.out, System.err, or text files. println automatically flushes. The following simple menu system illustrates the println and flush statements:

println <err> [[*
  0) Clobber All
  1) Build All
  2)   Generate Parser
  3)   Build Base
  4)   Build Extension
  5) Create Shipment
  6) Archive All
  x) Exit
*]];
flush <err> 'Enter your choice: '; // Don't use print!
opt = readLine();
switch opt {
case 0:  clobberAll(); break;
case 1:  buildAll();   break;
case 2:  genParser();  break;
case 3:  buildBase();  break;
case 4:  buildExt();   break;
case 5:  shipIt();     break;
case 6:  archive();    break;
default: exit 0;
}

JDBC scripting frequently prints reports. The print statements' formatting facility is easy and effective:

x = 100;
println x :<10;

The :<10 expression tells the print statement to print the value aligned to the left, with a width of 10. Similarly, you can write :>10 for a right-aligned value. For floating-point numbers, you can align numbers along the decimal point:

dollars = [ 0.10, 1000.981, 40.496 ];
for d in dollars {
  println d :*8.2;
}

The result is:

       0.1
    1000.98
      40.5

And you can repeat a string by specifying the repeating factor in {} following the item:

x = 'Underline This';
println x, nl, '-' {x.length};

nl is a literal for newline. The result is:

Underline This
--------------

Working with spreadsheets (CSVs)

Spreadsheets can be easily exported into CSVs for processing. The string type has a csv() method that parses a CSV into an array. Text files can be easily read in via the do..as lines statement. The following example has two functions; one loads a CSV into a table, the other downloads table data into a CSV:

// Load data into a database table
function loadEmp csvFile {
  prepare upd:
    INSERT INTO emp(emp_no,first_name,last_name,birth_date,salary)
VALUES(?,?,?,?,?)
  ;
  do csvFile as lines {
    cols = $_.csv();
    executeUpd upd with @1        = cols[0],
                        @2        = cols[1],
                        @3        = cols[2],
                        @4:date   = cols[3].parseDate('yyyy-MM-dd'),
                        @5:number = cols[4];
  }
}
// Export data from a database table into a CSV
function exportEmp csvFile {
  file = openTextFile(csvFile, 'w');
  executeQuery qry:
    SELECT emp_no,first_name,last_name,birth_date,salary FROM emp
  ;
  while qry.next() {
    println <file> qry[1], ',', qry[2], ',', qry[3], ',',
                   qry[4].fmtDate('yyyy-MM-dd'), ',', qry[5];
  }
  file.close();
}

SAX and SGML scripting

JudoScript has a handy XML scripting statement, do..as xml. Suppose we have an XML file, data.xml:

<order>
  <number>0004357</number>
  <date>2002-9-23 23:12:1</date>
  <name>James Huang</name>
  <email>jhuang@nospam.nospam</email>
</order>

We want to print the order data in a flat file:

fout = openTextFile('orderinfo.txt', 'w');
do 'data.xml' as xml {
  <order>:      println <fout> '=======================';
  </order>:     println <fout> '-----------------------', nl;
  TEXT<number>: println <fout> 'Order number:   ', $_;
  TEXT<date>:   println <fout> 'Order date:     ', $_;
  TEXT<name>:   println <fout> 'Customer Name:  ', $_;
  TEXT<email>:  println <fout> 'Customer EMail: ', $_;
}
fout.close();

The do..as xml statement should be intuitive: when the XML parser encounters a tag, say, <order>, that tag's handler code (stored in variable $_) executes, which is SAX (Simple API for XML)-style processing. JudoScript goes one step further by providing the TEXT<tag> syntax, which captures the text enclosed by an open and close tag.

JudoScript also has a similar statement, do..as sgml, for SGML/HTML scraping. The following example, html_table_check.judo, is a utility that prints the HTML table structures. It takes a command-line parameter (in #args[0]) as the HTML filename:

// Takes a HTML file and prints out all HTML table tags
indent = 0;
do #args[0] as html { // Or as sgml
<tbody>:                    printTag $_, indent;
<table>,<tr>,<td>,<th>:     printTag $_, indent;  
++indent;
</table>,</tr>,</td>,</th>: --indent;  printTag $_, 
indent;
}
function printTag tag, indent {
  println '  ' {indent}, tag, ' @ ', tag.getRow(), ',', tag.getColumn();
}

We have seen many useful features for data processing, many of which are used in the following case study. Before finishing with JudoScript programming, let's see what other functional areas JudoScript supports.

A perusal of other major functional features

JudoScript has other functional features worth noting in addition to JDBC scripting, XML scripting, and SGML scripting.

Send mail

The sendMail statement mimics an email client. It is used in the case study.

Execute native executables

The exec statement supports a sophisticated command line that mimics OS shells; you can specify the starting directory and environment variables, and can feed input and receive output simultaneously.

File and archive operations

copy is a versatile command that can copy files between directories and zip, jar, tar, and gzip archives (GNU zip). There are other commands, such as list, move, chmod, chgrp, and chown.

Schedule

The schedule statement can launch tasks in numerous ways, one of which is used in the case study.

Windows ActiveX scripting

ActiveX objects are obtained via the createActiveXComponent() function. Then, the objects' properties and methods can be accessed and invoked like any other object.

Java GUI scripting

You can easily assemble Java AWT (Abstract Window Toolkit) or Swing applications.

Internet and system scripting

Many system functions can make these tasks easy.

A J2EE case study

For our case study, we are going to write an offline batch order processing job for an e-commerce site, Crescent Online Shopping. The e-commerce system works asynchronously—when a customer places an order, the system stores the event in a queue (which is a simple database table). An offline batch job picks up orders in that queue and invokes an external Web service to finish the credit card transaction. The customer is notified of the final order status by email.

We have two challenges: First, The e-commerce system was built on top of a "commerce server" J2EE framework. That framework stores key entities (such as order, order line, and inventory) as Java objects in the database; i.e., Java objects are serialized in a proprietary way and stored in the database as BLOBs (binary large objects). Business information can be accessed only through the J2EE application. SQL is completely defeated—database administrators can't manipulate data in any way, and reporting tools can only report on a simple count.

The second challenge is the event queue. Instead of storing major event information in table columns, the information is encoded as XML and stored in a single column. Again, this defeats SQL.

Though odd, this architecture is based on real-world cases. This case demonstrates the power of JudoScript, which you can apply to other situations. Here is the pseudo-code for this offline job:

for all unprocessed order events in the queue
  decode the XML message;
  locate the order information through the J2EE application;
  call the credit card processing web service to do the transaction;
  set the processing result to the order;
  update the event queue;
  send notification to customer;
end for;

I next explain the solutions for all pieces, and eventually put them together in a single script.

Get and decode the event

The event queue table is simple:

CREATE TABLE event(
  queue_id     INTEGER       PRIMARY KEY,
  message      VARCHAR(1000) NOT NULL,
  status       INTEGER       NOT NULL,
  create_time  TIMESTAMP     NOT NULL,
  process_time TIMESTAMP
);

The status column indicates this event's status. A 0 value means new order, 1 means order processed successfully, and values of 2 and greater indicate failures. The message column holds XML data like this:

<order>
  <number>0004357</number>
  <date>2002-9-23 23:12:1</date>
  <name>James Huang</name>
  <email>jhuang@nospam.nospam</email>
</order>

The outer loop in the pseudo-code and the XML message-decoding look like this:

executeQuery qry: SELECT message FROM event WHERE status = 0;
while qry.next() {
  // Get the order info by parsing XML
  order_num  = null;
  order_date = null;
  do qry.message.getReader() as xml {
    TEXT<number>: order_num = $_;
    TEXT<date>:   order_date = parseDate($_, 'yyyy-MM-dd hh:mm:mm');
  }
  // Process it
  ......
}

In the do..as xml statement, getReader() is a string method that returns the string content; without the getReader() call, qry.message is a string and would be interpreted as a filename. We grabbed the text strings between the two tags and turned them into order number and date.

Invoke the J2EE application

The J2EE application runs on a WebLogic server. JudoScript has an initialContext() system function and numerous helper functions for popular J2EE application servers, such as WebLogic:

ctx = weblogicContext('t3://localhost:7301', 'weblogic', 'system32');
orderMgrName = 'crescent.ejb.order.OrderManagerHome';
orderMgr = ctx.lookup(orderMgrName).cast(orderMgrName).create();
order = orderMgr.findByPK(pk);

The first line uses JNDI (Java Naming and Directory Interface) to get a context object, which is used to look up the EJB (Enterprise JavaBean) manager home interface on the third line. cast() is a method for any Java object in JudoScript. Usually it is not needed, but in the case of EJB, the object returned by lookup() is a stub that may or may not be public, therefore an explicit casting is needed.

Invoke the credit card processor Web service

The credit-card-processing service provider supplies a Java API that wraps the underlying Web service. We built a Java class that wraps that service to cater to our specific needs. So we only need to instantiate our own wrapper and call its methods:

ccp = new
java::crescent.CreditCardProcessor('http://creditcard.processor:7501','credit','card');

Putting it together

Now that we have all the pieces, let's finish the job. We add another twist, making it a scheduled job that repeats itself every 24 hours; it can be run in the background or as a Windows service. Here is the complete source code:

startTime = Date();
startTime.hour   = 2;
startTime.minute = 0;
startTime.second = 0; // Start at 2:00 AM everyday
schedule starting startTime repeat 24*3600000
{
  // -- Prepare connections and other resources --
  connectMailServer 'my.mail.server';
  ctx = weblogicContext('t3://localhost:7301','weblogic','system32');
  orderMgrName = 'crescent.ejb.order.OrderManagerHome';
  orderMgr = ctx.lookup(orderMgrName).cast(orderMgrName).create();
  ccp = new
java::crescent.CreditCardProcessor('http://creditcard.processor:7501','credit','card');
  connect to 'jdbc:oracle:thin:@dbserver:1521:dbname', 'dbuser', 'dbpass';
  prepare upd: UPDATE event SET status=?, process_time=? WHERE queue_id=?;
  // -- Find and process unprocessed orders in the queue --
  executeQuery qry: SELECT queue_id, message FROM event WHERE status = 0;
  while qry.next() {
    // Get the order info by parsing XML
    order_num  = null;
    order_date = null;
    cust_name  = null;
    cust_email = null;
    do qry.message.getReader() as xml {
      TEXT<number>: order_num  = $_;
      TEXT<date>:   order_date = $_.parseDate('yyyy-MM-dd hh:mm:ss');
      TEXT<name>:   cust_name  = $_;
      TEXT<email>:  cust_email = $_;
    }
    // Find the order and process it
    order = orderMgr.findByPK(order_num);
    status = ccp.handleOrder(order);
             // status = 1 for success, > 1 for failure
    // Update the queue for the processing result
    executeUpdate upd with @1           = status,
                           @2:timestamp = Date(),
                           @3           = qry.queue_id;
    commit();
    // Notify the customer
    sendMail
        from: 'customer_support@crescent.cum'
          to: cust_email
     subject: 'Your Crescent order #' + order_num +
              ' is completed. Thank you!'
    htmlBody: [[*
      <p>Dear (* cust_name *):</p>
      <p>You order # (* order_num *)
      (* status==1 ? 'is completed' : 'has failed' *).
      Thanks for shopping with <em>Crescent</em>!</p>
      <p>Sincerely,<br>Crescent Customer Support</p>
    *]]
    ;
  } // End of while qry.next().
  // -- Clean up --
  catch:   println <err> $_; // print the exception
  finally: { disconnect(); catch: ; }
           { disconnectMailServer(); catch: ; }
} // End of schedule.

Lessons learned from this case study

Our fictitious system is based on real-world scenarios, involving many contemporary technologies. With JudoScript's highly abstract functional features, a terse script like the last listing can accomplish so much. We have used JDBC scripting along with Java scripting, JNDI, EJB, SAX scripting, sendMail, and schedule. The script is intuitive and all about business. This means great productivity, flexibility, and maintainability. Life is not perfect; difficult situations do exist for one reason or another. JudoScript can be a panacea for most issues and can make your life much easier.

JudoScript and other languages

Programming languages are roughly categorized as system languages and scripting languages. System languages, such as C, C++, and Java, are usually strongly and statically typed, compiled, and highly orthogonal. Orthogonal means having a limited set of rules to cover all possibilities. System languages are designed to create flexible software systems that are less likely to contain obvious bugs.

Scripting languages loosen the constraints on all these fronts to create an easier programming environment. They tend to use less strongly and dynamically typed systems, are usually interpreted, and break "orthogonality" by introducing so-called syntactic sugar, so in certain situations, the code becomes extremely handy and nifty.

JudoScript, being a functional scripting language, goes one step further than syntactic sugar for programming. JudoScript incorporates abstract, high-level domain support for today's common computing tasks. Therefore, its code is more intuitive, productive, and elegant. Let's compare JudoScript to other languages.

The "signal/noise ratio"

JudoScript code tends to be shorter and more germane to problems than code in other programming languages. I have converted a day-to-day utility written in Java into JudoScript. Both are well formatted and documented. The numbers are illustrated in Table 1.

Table 1. Size comparison for a utility

 JudoScript Java
Number of lines192344
Number of bytes6,52312,790

If we cut off the documentation, JudoScript is 50 percent the size and line numbers of the Java-based utility. What does this mean? If JudoScript code were all about business, then 50 percent of the corresponding Java code would be totally useless. The productivity and maintainability would be worse than 50 percent off, because the true logic is submerged in an ocean of noise. The signal/noise ratio reflects how well one can recognize useful information in the received signal. In the context of program source code, a higher signal/noise ratio equates to better readability and understandability.

Table 2 illustrates the remarkable difference between JudoScript code and Java code.

Table 2. Signal/noise ratio comparison for utility

 JudoScript Java
Assumption5 percent for nonbusiness code50 percent for nonbusiness code
Signal-noise ratio201
AnalogyTV with cableTV with poor antenna reception

By no means am I criticizing Java! I am just pointing out that Java is not right for this job. Also, the numbers are based on a particular case and are only demonstrative. The key is to find the right solution and tools based on your own situation. That solution may be another language or something you are already familiar with, but you should be aware of what is available and what you may be missing.

Express yourself directly and coherently

JudoScript's functional statements generally allow you to specify, or declare, what you want to do. In contrast, all other programming languages, including other scripting languages, allow you to program (or assemble) software. Such is the difference between 4GLs (fourth-generation languages) and 3GLs (third-generation languages). Table 3 compares two code snippets in JudoScript and Perl.

Table 3. 4GL vs. 3GL

  JudoScriptPerl
Code snippet

prepare qry:

SELECT * FROM emp

WHERE last_name = ? AND

salary < ?;

executeQuery qry with

@1 = 'Lin',

@2:number = 50000.0;

$sth = $dbh->prepare( "

SELECT * FROM emp

WHERE last_name = ? AND

salary < ?

" );

$sth->bind_param( 1, "Lin", SQL_VARCHAR );

$sth->bind_param( 2, 5000.0 );

$sth->execute( );

Thinking processPrepare the statement; run the query with these parameters.Prepare the statement; bind one parameter; bind another parameter; execute query.
StyleLook at the code and see how focused JudoScript code is. 

Another classic example is sendMail versus Java code using javax.mail.*. To send an email using the javax.mail API, you must create many objects to represent addresses and various parts of the message, assemble them appropriately, and find a right transport method to deliver. In JudoScript, the sendMail statement makes this a no-brainer, as demonstrated in the case study.

The key difference: 4GLs let you directly focus on the business, while 3GLs let you focus on coding software, and the software in turn does business. An analogy is starting a car. With 3GLs, you pull levers and flip switches in a designated sequence to start the ignition and move the vehicle. You can pull levers and flip switches in different ways, which proves more flexible; but that approach is cumbersome, requires much knowledge unrelated to your intention—moving the car—and is error prone. With 4GLs, you're driving an automatic-shift: you insert and turn the key, change the gear to forward, and push the gas pedal. Every move is germane to your purpose, and a layman like me can drive a truck as long as it is automatic-shift!

JudoScript, being a 4GL atop a general-purpose Java scripting language, provides the best of both 3GLs and 4GLs. If you truly hate to send mail that easily (with sendMail), you can call the javax.mail API in JudoScript with no limitations whatsoever. You may want to do this to practice using new Java APIs, or prototype a Java package, or for any other reason.

Code in context

Suppose you know nothing about SAX programming; look at the following code snippets in JudoScript and Java.

Table 4. SAX Programming in JudoScript and Java

 JudoScript Java
Code snippet

do 'data.xml' as xml {

<order>:

println '==============';

TEXT<number>:

println 'number: ', $_;

}

public class OrderFinder extends HandlerBase {

public OrderFinder() { super(); }

public void characters(char[] buf, int start, int len) {

//... process text surrounded by certain tags.

}

public void startElement(String elem, AttributeList as) {

if (elem.equals("order")) {

System.out.println("==============");

} else if (elem.equals("number")) {

//... process

}

}

public void endElement(String elem) {

if (elem.equals("number")) {

//... process

}

}

}

CommentYou'd probably guess this code is processing an XML document and that certain tasks occur for certain tags.You see a Java class with disparate methods. You need to guess really hard to fathom what they do based on their method names, parameter lists, and their correlations.

If you don't understand SAX and its framework, you may not have a clue looking at the Java code. If you look at the JudoScript code on the left in Table 4, you can probably figure out what it does immediately, because everything is right in your face. The code is exactly in the context, or your mindset, of processing an XML document.

General programming

JudoScript's general programming is simple and powerful. It does not reinvent the wheel; it simply uses a JavaScript-like syntax and programming model, but has more powerful datastructures and supports genuine object-oriented programming. For instance, the Object type has more useful methods than its JavaScript counterpart; it has a TableData type for in-memory 2D data processing. JudoScript treats all objects equally. You can script Java objects, arrays, and class objects as well as Windows ActiveX objects in the same way.

Conclusions

The synergy of functional support and programming power makes JudoScript a perfect tool for data processing and other computing tasks. Built on top of Java, JudoScript exposes the usability of the Java platform in a familiar and intuitive manner. It provides a convenient, unified, and unlimitedly extensible way to handle today's rich information formats and varied operations at the OS, application server, application, and distributed infrastructure levels.

Functional languages tell computers what to do, where programming languages tell computers how to do something. Functional support, or domain support, historically materialized in 4GLs. (3GLs are high-level programming languages, including Fortran, C, C++, Java, C#, Visual Basic, Perl, Python, etc.; 2GLs are assembly languages; and 1GLs are machine languages. The higher the G, the more abstract the L.) Traditionally, 4GLs are domain-specific, that is, languages have syntax and constructs to support specific domain knowledge. JudoScript is likely the first general- and multi-purpose 4GL, built atop a powerful 3GL engine and the Java runtime.

JudoScript's functional support goes one step further than syntactic sugar in normal scripting languages. This may raise concerns that the language is too hard to learn because of many nonorthogonal syntactic rules. If you understand the benefits of these functional features, then that is a small price to pay. The syntactic rules for functional support are simple, intuitive, and easy to memorize. The learning curve is not an issue.

Traditional scripting languages start with Perl and, frankly, none has substantially surpassed Perl. If you think in terms of a language's domain support, Perl supports two domains: general programming and text processing. Both are rather low-level but represent a big stride over system languages and provides greater productivity.

Today, many Java scripting languages are available and new ones keep popping up, which is not surprising because Java is a perfect platform for designing scripting languages. Using the domain-support analysis again, all Java scripting languages support at least two domains: general programming and Java object/class scripting. These two domains are low-level; the cool thing is Java scripting languages can use Java software as their native libraries.

JudoScript supports not only low-level domains such as general programming, Java scripting, and text processing, but also high-level, abstract, and functional domains, such as SQL, XML, SGML, email, filesystem and operating system operations, and schedules. To my knowledge, JudoScript is the only language that blends 4GL and 3GL features coherently and covers most of today's popular computing tasks in today's Internet era. JudoScript is in its own category of functional scripting languages. It is a language for use by any computer programmer, and Java developers can reap the most from it.

JudoScript is a product of our time. Today, many modern computing technologies are becoming norms; these norms deserve to be supported natively in functional scripting languages, and JudoScript pays the respect. It is this native support for popular technologies, big and small, that sets JudoScript apart from the rest of the crowd. After all, the reason why we script is to easily and naturally instruct computers to do what we need. Perl tried that 20 years ago; now, JudoScript tries again.

James Jianbo Huang is the author of the JudoScript language. Huang holds an MS in electronics, and favors creating software and solutions; many of the solutions he has created over the years are now features in JudoScript. He enjoys music and sports but does not practice judo.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more