The Java module allows you to access Java classes, objects, and arrays directly from the WebL programming language. This functionality provides practically transparent access to any functionality provided by Java class library, at the extra run-time cost of translating between WebL and Java data types. The direction of access is purely from WebL to Java; transparent Java to WebL access is not possible without changes in the Java virtual machine. Note that using module Java requires a knowledge of Java itself and some knowledge about the WebL implementation, which is beyond the scope of this user manual.
The WebL-to-Java integration works by automatically "wrapping" Java objects, classes, and arrays with special WebL types, and performing transparent translation of WebL data types to Java data types and vice-versa. The Java module introduces two new WebL data types for this purpose. The WebL "j-object" type is a special object type that wraps Java objects and Java classes. The WebL "j-array" type wraps Java arrays.
Wrapping a Java object in a WebL j-object is transparent to the WebL programmer. From the WebL programmer's perspective, the object behaves exactly the same as a normal WebL object. That is, the fields and methods of a Java object is directly accessible from the WebL j-object. For example, the following WebL code creates a Java Date object, and calls some of its methods to print out some of the details of the data object:
var D = Java_New("java.util.Date");
PrintLn("Today's date is ", D.toString());
PrintLn("Today is ", D.getMonth());
Notice how the last line prints out the Java object itself. The console output from this statement might look as follows, which illustrates that the methods and fields of the Java date object are reflected 1-to-1 inside the WebL j-object:
[. "setYear" = < setYear(int): void>,
"getSeconds" = < getSeconds(): int>,
"parse" = < parse(java.lang.String): long>,
"setTime" = < setTime(long): void>,
"setHours" = < setHours(int): void>,
"setMonth" = < setMonth(int): void>,
"notifyAll" = < notifyAll(): void>,
"after" = < after(java.util.Date): boolean>,
"setDate" = < setDate(int): void>,
"getHours" = < getHours(): int>,
"setSeconds" = < setSeconds(int): void>,
wait(long,int): void wait(): void>,
"getMonth" = < getMonth(): int>,
"toString" = < toString(): java.lang.String>,
"UTC" = < UTC(int,int,int,int,int,int): long>,
"getYear" = < getYear(): int>,
"before" = < before(java.util.Date): boolean>,
"equals" = < equals(java.lang.Object): boolean>,
"getTime" = < getTime(): long>,
"getTimezoneOffset" = < getTimezoneOffset(): int>,
"getMinutes" = < getMinutes(): int>,
"hashCode" = < hashCode(): int>,
"getClass" = < getClass(): java.lang.Class>,
"getDate" = < getDate(): int>,
"setMinutes" = < setMinutes(int): void>,
"toGMTString" = < toGMTString(): java.lang.String>,
Furthermore, automatic translation between WebL and Java data types is done when calling methods and constructors, or assigning values to object fields. See Conversion of WebL types into Java types , shows with what Java types a specific WebL type is compatible with. Refer to this table when calling a Java method or constructor. Refer to See Conversion of Java types into WebL types , to see how values returned from methods and field accesses are converted back into WebL types. Studying these two tables will show that the type conversion is mostly restricted to converting between primitive Java and WebL types. That means for example that WebL objects can only be passed to methods that accept the implementation type of WebL objects (webl.lang.expr.ObjectExpr). This is not restrictive as it might sound; many methods in the JDK accept java.lang.Object's as arguments, which is of course a superclass of webl.lang.expr.ObjectExpr. For example, it becomes possible to insert WebL objects into Java hash tables.
Here is a more complicated example which reads and numbers the lines of a file called "test.txt":
var System = Java_Class("java.lang.System");
var F = Java_New("java.io.File", "test.txt");
var R = Java_New("java.io.BufferedReader",
Java_New("java.io.FileReader", F));
After each occurrence of R.readLine, the resulting line is converted into a WebL string type. When System.out.print(ln) is called, the WebL types are converted back into the appropriate Java type.
The above example also illustrates how to access a static field (namely System.out): The Java_Class function wraps the class into a WebL object, from where the field can be accessed directly. In addition, the example also shows how to use constructors with arguments.
WebL programmers should be aware that constructors and methods are often overloaded in Java. In this case, WebL will attempt to match the best constructor or method by comparing the actual arguments (provided in WebL) with the formal arguments of the constructors and methods in question. This might lead to problems when the matching involves numeric types. Suppose a Java method named X is overloaded three times, with single formal arguments of type int, short, and byte respectively. Which instance of X will be called when a formal argument of type int is used in a call the function? WebL's approach is to prefer the "widest" type, which in this case would be X with the formal of type int. Programmers should be aware that this simple heuristic might cause the "wrong" instance of the overloaded method to be invoked. There is no support for enforcing calls to a specific overloaded method in WebL.
In addition to the j-object type, the Java module also provides a new type called j-array that wraps Java arrays. The reasoning behind providing a separate array type instead of using an established data type such type list, is that Java arrays are fundamentally different from WebL data types. Java arrays are mutable (i.e. elements can be overwritten), whereas WebL types (except for type object) are immutable. Thus passing a WebL list to a method that expects a Java array begs the question want would happen if the method mutates the array.
The Java array support in module Java includes functions to allocate an array of a specific type and size (Java_NewArray), retrieve an element at a specific index (Java_Get), and overwritting an element at a specific index (Java_Set).
The following program allocates, writes and reads the elements of an array:
var A = Java_NewArray("int", 10);
Java_Set(A, 1, "hello"); // -> Type mismatch exception