Using NetRexx

NetRexx is a programming language designed to make programming the Java Virtual Machine easier than with Java. Although NetRexx syntax is derived from Rexx, NetRexx is strongly typed, making it first-rate for programming the JVM and allowing access primitive (binary) datatypes.



April 01, 1998
URL:http://www.drdobbs.com/jvm/using-netrexx/184410534

NetRexx is a programming language designed as an alternative to Java. The idea behind NetRexx, which was created by IBM Fellow M.F. Cowlishaw (who also designed Rexx), is to make programming the Java Virtual Machine (JVM) easier than with Java. Although NetRexx syntax is derived from Rexx, NetRexx is strongly typed, making it first-rate for programming the JVM and allowing access to primitive (binary) datatypes. NetRexx compiles to Java bytecode, and NetRexx classes and Java classes are equivalent. In short, when your development requirements include web programming or other applications for the JVM, you may well find it easier and more productive to program in NetRexx than Java.

NetRexx is freely available under IBM's Employee Written Software agreement and can be downloaded from http://www2.hursley.ibm.com/netrexx/ as either a ZIP file or a UNIX tar.Z file. It comes with instructions for installation and use, and also includes extensive documentation on the language definition and keyword instructions. Cowlishaw's book, The NetRexx Language (Prentice Hall, 1997), provides a complete reference.

Because NetRexx programs run on the JVM, they are fully portable and can be executed on any platform where Java is present. This includes Windows, OS/2, many flavors of UNIX, OS/390, and (soon) VM.

A NetRexx program contains the following:

As with Rexx, you don't need to declare variables before using them. NetRexx automatically determines the proper type of a variable from the context of its first use. Properties must be defined at the beginning of a class. Though it is not necessary to explicitly type them, it may be convenient to do so at this point. All other variables are local to the method that uses them.

Terms in NetRexx are evaluated in a simple and intuitive fashion that may be new to many programmers. NetRexx evaluates each term in the context in which it is first encountered. This allows new keywords to be added to the language without breaking existing programs. Simplified, the full search order is as follows:

In Example 1, the select in the first line of the action method is recognized as a NetRexx keyword. However, if you insert select = 'blotz' at the beginning of that method, then the select appearing alone in a clause would have been detected as an error by the NetRexx compiler -- "unexpected use of local variable." Using select as a local variable in another method in the class would not preclude its recognition as a keyword in this method.

Example 1: The action method.

NetRexx also uses compound terms, which are evaluated from left to right as in Java. Thus, the term u.left(1) is the value of the term u, to which the NetRexx method left is applied with an argument of 1.

The Rexx Class

Recall that you don't have to declare variables in NetRexx. However, to be a first-class language for the JVM, NetRexx must be strongly typed. This can be largely transparent to the programmer, however, because NetRexx provides a default type for variables, the Rexx type, which is equivalent to the strings of the classic Rexx language. The NetRexx compiler automatically performs the necessary type conversion when translating a program to Java bytecodes.

Using variables of type Rexx significantly increases programmer productivity. You are freed from concern over the types of variables in a program, and the number of keystrokes required to type in the program is reduced.

The variables registered, u, p, and NameList in Listing One are all of type Rexx, but they came to this state from different directions:

Listing One

/* Registry.nrx  --  Applet for users to access private information */class Registry extends Applet        -- inherit from & extend the Applet class
properties private                   -- class and/or instance variables
  bclear = Button("  Clear  ")       -- Java Button class
  breg = Button("  Register  ")
  bacc = Button("  Access  ")
  name = TextField(15)               -- Java TextField class
  pw = TextField(15)
  statlbl = Label
  NameList = Rexx
method init                          -- initialization method
  LoadList                           -- initialize the names array
method start
  setLayout(BorderLayout())          -- our frame's layout (Java methods)
  setBackground(Color.white)
  setForeground(Color.blue)



  p1 = Panel()                       -- a different layout for the buttons
  p1.add(bclear)
  p1.add(breg)
  p1.add(bacc)
  add("Center", p1)



  stat = Panel()
  statlbl = Label(" ".copies(100), Label.CENTER)
  stat.setBackground(Color.white)
  stat.setForeground(Color.red)
  stat.setFont(Font("Helvetica", Font.BOLD+Font.ITALIC, 22))
  stat.add(statlbl)



  add("South", stat)                 -- add the panel to the frame



  p2 = Panel()                       -- a container for the "center" stuff
  p2.setLayout(BorderLayout())       -- but we want some control
  p2.setBackground(Color.blue)       -- set fg and bg colors for this area
  p2.setForeground(Color.white)



  p3 = Panel()                       -- one piece of the "center" stuff
  ulabel = Label("Enter Username:")  -- some label text
  name.setBackground(Color.white)    -- fg and bg colors for the text field
  name.setForeground(Color.black)
  p3.add(ulabel)                     -- populate this piece
  p3.add(name)



  p4 = Panel()                       -- another piece of the "center" stuff
  plabel = Label("Enter Password:")  -- some label text
  pw.setBackground(Color.white)      -- fg and bg colors for the text field
  pw.setForeground(Color.black)
  pw.setEchoCharacter(char "*")      -- echo character for sensitive data
  p4.add(plabel)                     -- populate this piece
  p4.add(pw)



  p2.add("North", p3)                -- now put the two pieces into the
  p2.add("South", p4)                --  "center stuff" container
  add("North", p2)                   -- and add that container to the frame



/* Handle an action (button press) */
method action(e=Event, o=Object) returns boolean
  select
     when e.target = bclear then do  -- if Clear button,
        name.setText('')             --   set contents of text fields
        pw.setText('')               --   to null
        statlbl.setText(String " ")  -- and clear message area
        return 1
        end

     when e.target = breg then do            -- if Register button,
        if Register then Status("RegOK")     -- and successful,
        return 1                             -- put up nice dialog
        end
     when e.target = bacc then do            -- if Access button,
        if Valid then AccessPrivate          --  if registered, let them in
           else Status("BadID")              -- otherwise, an error dialog
        return 1
        end
     otherwise return super.action(e, o)     -- other action we don't handle
     end



/* Sign up a new user */
method Register
  u = Rexx name.getText              -- get contents of text fields
  p = Rexx pw.getText
  if u = '' then do                  -- if username missing,
     Status("NOUSER")                --   put up message to tell them
     return 0                        --   that's a no-no; and return
     end                             --   failure
  if p = '' then do                  -- if password missing,
     Status("NOPW")                  --   put up message to tell them
     return 0                        --   that's a no-no; and return
     end                             --   failure
  NameList[u] = p                    -- otherwise, add to list
  return 1                           --   and return success



/* Validate the current user */
method Valid returns boolean
  u = Rexx name.getText
  if u = '' | u.left(1) = ' ' then return 0
  registered = 0
  loop thisname over NameList
     if u == thisname then do
       registered = 1
       leave
       end
     end
  if \registered then return 0
  p = Rexx pw.getText
  if NameList[u] \== p then return 0
  return 1



/* Put some initial users into the list */
method LoadList
  NameList = ''
  NameList['mickey'] = 'ClubLeader'
  NameList['minnie'] = 'mouseketeer'
  NameList['donald'] = 'aDuck'



/* Status Reporting */
method Status(reason='')
  select
     when reason = "RegOK"  then msg = "Registration Complete!"
     when reason = "NoUser" then msg = "Error:  Username Required"
     when reason = "NoPW"   then msg = "Error:  Password Required"
     when reason = "BadID"  then msg = "Error:  Userid and/or Password 
                                                       Missing or Invalid"
     otherwise msg = "Error: Unknown error; get help"
     end
  statlbl.setText(String msg)
method AccessPrivate
  statlbl.setText(string "Welcome to the Private Area")
  /*
     addr =          -- specify URL address here
     url = URL(addr)
     statlbl.setText(String url.getContent)
   */

In addition to simple strings, the Rexx class supports traditional arrays with a numeric index in square brackets. Of course, NetRexx arrays may be multidimensional. It is not necessary to reserve storage -- simply assign elements as needed.

An even more interesting feature of the Rexx class is the indexed string, which is similar to a traditional array, but for which the indexes are literal strings rather than numbers (like a Java HashTable). Thus, you might populate an indexed string simply by assigning elements:

   method LoadList
NameList = ' '
NameList['mickey'] = 'ClubLeader'
NameList['minnie'] = 'mouseketeer'
NameList['donald'] = 'aDuck'

Indexed strings also behave like arrays in that one may execute a series of instructions on all elements by looping over the indexes. The loop instruction in Example 2(a) does just this.

Example 2: Two equivalent pieces of code.

During each iteration of the loop, the variable thisname takes on the value of the next index. For arrays with numeric indexes, the indexes are processed in numerical order. For indexed strings, the order of selection cannot be predicted.

Because Rexx variables are strings and humans generally perceive even significant portions of program execution in terms of strings, NetRexx includes string manipulation methods. Most of the popular built-in string manipulation functions from Rexx are available as NetRexx methods.

There is also an exists method to determine if a particular index to an indexed string exists. Using this method, Example 2(a) can be simplified to Example 2(b).

From NetRexx to Java and Back Again

NetRexx uses the Java object model, so Java classes may be invoked directly from NetRexx just as if they were NetRexx classes. The converse is also true.

Listing One is a web-based registration form that must be completed for access to information from the server. (Listing Two displays the applet Registry.)

Listing Two

<html><body bgcolor="#ffffff">
<p>
This sample Web page displays the applet Registry.
<p>
The applet appears centered in the browser window just below
this text.
<p>
<br>
<center>
<applet code="Registry.class" width=500 height=150>
</applet>
</center>
<p>
<br>
<font size=2> Last modified: 30 April 1997 </font>
</body>
</html>

Listing One includes many examples of how you can use Java classes directly:

NetRexx does not need a keyword such as new to reserve storage for new instances of objects. Nor do you need to explicitly type cast the variable. NetRexx's stat=Panel() is functionally equivalent to Java's Panel stat=new Panel().

NetRexx's evaluation of compound terms from left to right is consistent with Java syntax. Invoking Java methods uses the same syntax as invoking NetRexx methods; and our sample is full of examples of using Java methods directly -- in the layout, color-scheme definition, and population of the applet's window and in retrieving (or clearing) user input.

Operators

NetRexx provides all the usual assignment, arithmetic, logical, and comparison operators but includes extensions as well. The "equals" sign (=) assignment operator may also be used to assign a type to a variable, as illustrated by statlbl = Label or NameList = Rexx. This devolves naturally from the search order for evaluating a term.

A unique operator is blank concatenation, in which a single blank between two terms concatenates their values with a blank in between: say 'Username:' uname yields Username: pjt when the value assigned to uname is "pjt."

NetRexx also uses the blank operator for typecasting as illustrated by u = Rexx name.getText (at the beginning of the Register method) where the value of name.getText is cast to type Rexx.

Methods Without Madness

NetRexx's method instruction fully supports the concept of a "method signature" as in other languages such as Java. A NetRexx method may also be defined with no signature, in which case it accepts no arguments, and any value it may return is of type Rexx. The LoadList and Register methods in our sample share these characteristics.

In the clause if Register then Status("RegOK"), the value returned from Register is treated as a Boolean. NetRexx automatically recognizes 0 and 1 (the possible return values) from Register as Booleans if the context requires, so explicit definition of the return type from Register is unnecessary. You may wish to do so for clarity, however, as in the Valid method.

Argument lists are supplied as a list of variables within parentheses immediately adjacent to the method name as illustrated by the action and Status methods. For the action method shown in Example 1, the argument types are explicitly declared. The Status method shown in Example 3 illustrates the use of optional arguments for which a default value is supplied and, in this case, the default type is Rexx. Both required and optional arguments may be specified, with the optional ones omitted from the right.

Example 3: The Status method.

Though they are not discussed here, other keywords are available to further qualify a NetRexx method.

Also of Interest

NetRexx supports two styles of comments. Block comments are delimited by pairs of /* and */ and may be nested. The --delimiter begins a line comment which is terminated by the line end.

Unlike Java, NetRexx is generally case-insensitive. This gives you the flexibility to use the capitalization style you prefer. Furthermore, normal comparison operators perform case-insensitive comparisons, freeing you from the problem of case in such operations as comparing user input to expected inputs or specifying method argument strings. In the Register method, the call Status("NOUSER") specifies an uppercase argument, but the Status method compares it to the mixed-case "NoUser." When case sensitivity is important, the strict comparison operators == and \== can be used.

The select construct (used in both the action method and the Status method) is the NetRexx equivalent of a case statement.

The action method (to handle button actions) is present because this sample was implemented for use with JDK 1.02. For JDK 1.1, this would be replaced with appropriate event listeners.

Conclusion

In the real world, the NameList would be populated from a file or database resident on the server rather than by the LoadList method. You might use Java classes for this, or you could use the NetRexx RXFile suite developed by Max Marsiglietti, which is accessible through the NetRexx home page.

The actual call to the server to load a restricted URL is commented out in my sample in favor of simply displaying a label that announces a successful connection. Reverse the commenting (and provide an appropriate URL, of course) to make this a live web application.


Pamela is Rexx/Java project manager for the Share Technology Conference, vice-chairman of NCITS Committee J18 for the Rexx Language, and is on the board of directors of the Rexx Language Association. She can be reached at pamela_taylor@ stercomm.com. Using NetRexx

Using NetRexx

By Pamela J. Taylor

Dr. Dobb's Journal April 1998

Example 2: Two equivalent pieces of code.


Copyright © 1998, Dr. Dobb's Journal

Using NetRexx

Using NetRexx

By Pamela J. Taylor

Dr. Dobb's Journal April 1998

Example 3: The Status method.


Copyright © 1998, Dr. Dobb's Journal

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.