ClientObject Tutorial
Introduction
In BBj 2.0 and higher, programmers can embed Java to access the full functionality of the Java language from within a BBj program. So, for example, a program might use the following code to print the current time using embedded (server-side) objects.
Print Time and TimeZone of Server Machine
|
In many configurations, the user display is on a different machine (the client machine) than that on which the BBjInterpreterServer is running (the server machine). Because these machines may be in different time zones, this small program may display results that are different from what the programmer intended. This code is executed within the Java Virtual Machine (JVM) of the server and so it will display the time and time zone of the server machine while the programmer may have wanted to display the local time on the client machine.
Prior to BBj 8.0, there has not been a mechanism by which a program could execute code within the JVM of the client. BBj 8.0 introduces syntax that provides an RMI (Remote Method Invocation) interface that allows the embedded Java code within a BBj program to access objects that reside in the client JVM rather than within the server JVM.
In order to access this RMI capability, append an @ symbol to a class name to indicate that the class will be accessed in the client JVM rather than in the server JVM as shown in the sample below using ClientObjects:
|
When this code is executed it will use the time of the client machine to create a new Date Object in the client JVM and will use the locale of the client to create a DateFormat object in the client JVM. The result of running this program will be to display the time and TimeZone of the client machine rather than the time and TimeZone of the server.
When objects are created in the client JVM those objects are referred to as client-side objects. The server-side variables that reference those client-side objects are referred to as ClientObjects. So, for example, when line 40 is executed a client-side instance of Date is created and the variable remoteDate! is a ClientObject that represents an RMI handle to that client-side object. The ClientObject can be manipulated in the same way as a server-side object.
This tutorial provides a short example of how to use ClientObjects. If unfamiliar with the use of Java objects within a BBj program, read the following references about using server-side embedded Java before attempting to use ClientObjects:
Objects in BBj (PowerPoint)
Exponentially Better Applications: Embedded Java and BBj (HTML)
Syntax of ClientObjects
There are three ways in which the @ symbol is used in BBj to indicate that embedded Java is to use ClientObjects; when
-
Creating a new ClientObject
-
Invoking a static method on a client-side class
-
Declaring a value to be a ClientObject
In each case, the @ is appended to the class name. The class name can be a fully qualified class name or it can be an abbreviated class name if the fully qualified class name has appeared in a USE statement.
The following sample shows the various uses of the @ character within a BBj program.
|
At lines 040-070 a number of variables are declared to be ClientObjects. At lines 090-110 two client-side objects are created and assigned to ClientObject variables. At lines 120-130, two static methods are called on client-side classes and the return values of those static methods are assigned to ClientObject variables.
Using a ClientObject
The methods of a ClientObject are called in the same way that the methods of other objects are called; by using the standard dot notation. In general, the parameters that are passed when calling a method on a ClientObject must themselves be ClientObjects. If a method accepts a string or a number then it will accept a server-side value (see the ClientObject vs. Server-side Objects section for details).
The return value of a method called on a ClientObject is again generally a ClientObject unless that return value is a number or a string. If the return value is a number or a string then the return value will be a server-side value.
This code sample calls methods on ClientObjects:
|
Running the code sample results in output similar to the following.
|
The toString() value of a ClientObject consists of the string "[CLIENTOBJECT]" followed by an ID followed by the toString() value of the client-side object.
Notice that looking at the output above, calendar! is a ClientObject and that the return value of calendar!.getTime() is also a ClientObject. If we place calendar! into a client-side HashMap and then retrieve it, we will receive the same ClientObject. And if we place the server-side number 456 into the client-side HashMap and then retrieve it, we will receive the server-side number.
The field values of a client-side object can also be accessed through the ClientObject and the static fields of a client-side class can be accessed by addressing that class using the @ symbol as shown below.
|
ClientObject vs. Server-side Objects
It is important to understand the difference between a ClientObject and a server-side Object. Any Object that was created using the '@' notation is a ClientObject. Any Object that was created without the '@' notation is a server-side Object. BBjAPI is a server-side Object. Any Object that is obtained through calls on BBjAPI is a server-side Object. In particular, all BBjControls are server-side Objects even though they 'represent' GUI Objects that exist on the client.
In general, the parameters passed to a ClientObject must be ClientObjects while the parameters passed to a server-side object must be server-side objects.
The exceptions to this general rule are:
-
Strings and Numbers are always server-side values. Strings and Numbers may be passed as parameters to methods of ClientObjects.
-
The method BBjWindow::addWrappedJComponent (which is a method call on a server-side object) accepts as a parameter a ClientObject.
-
A BBjControl (which is a server-side object) can be passed as a parameter to a ClientObject if that ClientObject represents a client-side swing component.
-
A BBj CustomObject (which is server-side object) can be registered as an event listener on a ClientObject that represents a swing component
These exceptions allow a program to place objects that extend javax.awt.JComponent@ (ie any client-side JComponent) onto a BBjWindow as well as to place BBjControls onto JComponents and to respond to events that occur on JComponents. All these use cases are demonstrated in the following sections.
Similarly, the return value of a method invocation on a ClientObject is itself a ClientObject and the return value of a method invocation on a server-side Object is a server-side Object except that:
-
Strings and Numbers are always server-side values.
-
BBjBarChart, BBjLineChart, and BBjPieChart (which are server-side Objects) each have a method getClientChart() which returns a ClientObject.
Placing a JComponent into a BBjWindowBBj 8.0 provides a new BBjWindow::addWrappedJComponent method that allows the program to create a BBjControl that contains a client-side Java Component. In order to place a client-side JComponent onto a BBjWindow, the program first creates a ClientObject that represents the JComponent and then 'wraps' the Object in a BBjWrappedJComponent by calling addWrappedJComponent. |
|
The following code creates a JButton with a thick green border (shown above) and places it onto a BBjWindow.
|
Registering a BBj Callback as a Listener on a JComponent
A BBj CustomObject may be registered as an event listener on a ClientObject by calling the add<some>Listener method of the ClientObject.
The CustomObject must have methods that 'correspond' to the methods of <some>Listener. Each of the corresponding methods of the CustomObject must have the same name as the method of the <some>Listener and must accept ClientObjects where the <some>Listener accepts events.
So, for example, the following code sample registers a CustomObject named Listener as a PropertyChangeListener on a JSplitPane. A PropertyChangeListener has a single method
void PropertyChange(PropertyChangeEvent event)
so the CustomObject, Listener, must have a corresponding method
void PropertyChange(PropertyChangeEvent@event)
with the same name but accepting a PropertyChangeEvent@ rather than a PropertyChangeEvent.
This sample adds a JSplitPane to a BBjWindow and registers a listener:
|
The screen that this code sample generates appears as:
Its console output appears as:
Mixing ClientObjects and BBjControls to Provide a BBjWindow with a LayoutManager
We are now in a position to build a program that provides an interesting mix of JComponents and BBjContols. The following sample provides a BBjWindow that contains a JSplitPane. The left side of the JSplitPane contains both BBjControls and JComponents. In addition, the left panel has a layout manager so that all the controls (both the JComponents and the BBjControls) change sizes as the separator of the JSplitPane is moved.
This code sample shows a mix of JComponents and BBjControls with a LayoutManager:
|
This sample generates this screen:
If the user moved the separator, the screen might look like this:
In addition to managing the Layout of the left panel, this sample also reports FocusGain and FocusLoss whenever the JTextField gains or loses focus and reports PropertyChangeEvents whenever the user moves the separator of the JSplitPane.
Requirements for Class files Used to Create ClientObjects
In order to create a ClientObject the Java Class file that defines the client-side Object must be visible to the server as well as the client.
In addition, if the Java Class file is not found in a 'privileged' jar file, then BBj will generate a 'nag' message unless the server is running with a DVK license. A jar file is privileged if it is part of the JVM Java Runtime Environment or if it is a 'registered' jar.
The charts.jar file shipped with BBj is a registered jar file. Developers can register their own jar files using Java's static method com.basis.jarRegistrationService.client.JarRegistrar.registerJar.
For example, register a Jar within a BBj program as follows:
|
For a full description of JarRegistration, refer to the JarRegistrar Class.
Once a jar file has been registered, it can also be signed without invalidating the BBj registration. However, any change to the files within the jar will invalidate the registration.