Extending a Remote Interface (subclassing an InformationBean)

Remote interfaces are implemented in a number of different ways. Some are implemented completely on the server. Others have a mixed client and server-side implementation.

This document describes how to extend a remote interface with both client and server-side implementation. Additionally, it lists the various client and server-side files that are associated with the interfaces. This document uses the MultidimensionalTableInterface as an example.

Note: In order to fully benefit from this information, you should be familiar with creating and editing SAS/AF SCL classes. For more information on this topic, refer to the SAS Guide to Applications Development book.

The first step in extending a remote interface is to determine if your subclass will need server-side implementation. If so, determine if you will be subclassing the SCL class used by the InformationBean that you are subclassing. In the example presented in this documentation, we intend to extend the existing SCL class and add an additional method. Therefore, we must determine the name of the SCL class that we need to subclass.

We must also determine the contextClassPath of the interface that we wish to extend. To do so, look at the reference documentation (available within webAF help) for the interface to see if the class is documented. If appropriate documentation is unavailable, consider using SASHELP.MONIKER, a dataset that contains a subset of the remote interfaces. This dataset maps interface names to appropriate SCL classes. You may view this dataset to determine the class that you need to subset.

In this document, we will be extending the MultidimensionalTableV3Interface, whose contextClassPath (a hidden property) is SASHELP.RSASMOD.MDTABLE.CLASS.

We need to create a subclass of this SCL class that we will use with our extended interface. In our example, we have decided to put the SCL subclass in a catalog referenced by MODELS.CUSTOM and call it MDDB. Therefore, we need to ensure that the MODELS libname is always defined by the remote SAS session. This can be accomplished by adding the libname statement to the autoexec that is executed by your spawner.

Using the SAS/AF class editor, create a new class named MODELS.CUSTOM.MDDB.CLASS (whose parent class is SASHELP.RSASMOD.MDTABLE.CLASS). Next, add a method named getFoo that returns char:

getFoo: method return=char;
put "Entering Server getFoo method";
dcl string(10) results = "Foo";
put "Leaving Server getFoo method";
return results;
endmethod;

It is often a good idea to create a standalone SCL test to instantiate and drive the new methods completely from the server before interfacing them with the client. This allows you to flush out any SCL coding errors without introducing client issues. For information on using the SAS/AF Class Editor to create and edit SCL classes, see the Developing Components section of the SAS Guide to Applications Development book.

Now that the server class is implemented and tested, we can set up the client implementation. First, we must create a project named custommddb that will provide a test environment for all our new classes. This can be done by selecting File->New from the webAF File menu; selecting the Projects Tab, and then selecting Applet Project. Enter custommddb for the project name. Select OK and then select Finish.

Next, we must create a new InformationBean. This can be done by selecting File->New from the webAF File menu; selecting the Components tab, and then selecting Remote Interface.

When creating a remote interface, you must specify a remote SCL class. To continue with our example, specify the remote SCL class that we just implemented: MODELS.CUSTOM.MDDB.CLASS.

We are going to place all of our custom remote interfaces into a package called com.sas.sasserver.custom. By default, the wizard names the interface using the SCL class name: mddbInterface.

The new mddbInterface will extend the com.sas.sasserver.mdtable.MultidimensionalTableV3Interface.

Use the default pathname for the interface location. This places the class within our project and makes testing easier. After we have completed the testing, we will package and move these classes to their appropriate location.

Once you select Finish, the wizard will create the mddbInterface.java file and open it in an editor for editing. If the only method(s) that you intend to add are server-side methods, you can edit the interface source, add these methods to the interface, and then compile the file. Once the methods are added, right-click your mouse on the source file and select Generate Remote Proxies. All the proxy files that you need to drive the remote methods will be generated, thereby creating an InformationBean from the Remote Interface.

/* Copyright (c) 2000 by SAS Institute, Inc */
package com.sas.sasserver.custom;
public interface mddbInterface extends com.sas.sasserver.mdtable.MultidimensionalTableV3Interface
{
String contextClassPath = "MODELS.CUSTOM.MDDB.CLASS";

/* Add new interface methods */
/* getFoo will be implemented on the server */
String getFoo();

If your extended interface requires additional client-side implementation, you will need to create a delegate class to house this implementation. Any method implementation found in the delegate class will be run locally on the client. All other methods will be proxied to the server for execution. The following code shows how to implement a getFooBar() method on the client:

public interface mddbInterface extends com.sas.sasserver.mdtable.MultidimensionalTableV3Interface
{
String contextClassPath = "MODELS.CUSTOM.MDDB.CLASS";

/* Add new interface methods */
/* getFoo will be implemented on the server */
String getFoo();

/* getFooBar will be implemented on the client by the */
String getFooBar();

/* mddbDelegate class */
}

Use the Class Wizard (File->New; Components Tab; Class item) to create a new class called mddbDelegate that extends MultidimensionalTableV3Delegate. The wizard will generate the class stub and you can then add any client-side implementation:

/* Copyright (c) 2000 by SAS Institute, Inc */
package com.sas.sasserver.custom;
public class mddbDelegate extends com.sas.sasserver.mdtable.MultidimensionalTableV3Delegate
{
public String getFooBar()
{
System.out.println ("Entering getFooBar");
String result = ((com.sas.sasserver.custom.mddbInterface)Imddb).getFoo() + Bar";
System.out.println("Leaving getFooBar result= " + result);
return result;
}
}

If you intend to include this InformationBean extension on your toolbar and if you want a customizer (in addition to the property sheet), then you must create a mddbInterfaceCustomizer class. To do so, use the Class Wizard to extend com.sas.sasserver.mdtable.multidimensionalTableV3InterfaceCustomizer.

Unless you intend to modify the customizer, the class stub is all that is needed. You simply need to compile it. Likewise, if bean property customizations are required, you must create an mddbInterfaceBeanInfo class that extends com.sas.sasserver.mdtable.multidimensionalTableV3InterfaceBeanInfo. Customizations that you may want to make to the BeanInfo include hiding properties or designating a property as an expert property. See the documentation for the com.sas.beans.ExtendedBeanInfo for more details.

To add your new InformationBean to the toolbar, select Tools->Edit Component Palette. For this example, we will add the new InformationBean as the first component on the existing SAS tab of the Component Palette.

First, select the SAS entry in the Tabs selector. Then, select the Add New Component button.

Next, select the component that you want to add to the tab. You may customize the icon and description for the component.

Now that your InformationBean is complete, you may begin using it just as you would any other InformationBean. The mddbInterface extends the multidimensionalTableInterface so that it can be used as the model for the multidimensionalTableView. Because you have added it to the toolbar, you can drop it on the multidimensionalTableView and proceed to set its attributes through the customizer or property sheet.

To test your new InformationBean, drop a MultidimensionalTableView onto the Viewer frame and subsequently drop your newly added mddbInterface Toolbar item onto the viewer. Additionally, drop a Pushbutton (which will be used to drive the new methods). Set up an event handler to drive the getFooBar method when the actionPerformed event is sent from the button. Set the required property values on the mddbInterface customizer to identify the source and the query you desire. Open the customizer for the connection object and select the Advanced tab. Turn on the Route SAS Server log to client System.out option. Build and execute the project. View the Component log to see output similar to the following:

Entering getFooBar
Entering Server getFoo method
Leaving getFooBar result=Foo Bar
Leaving Server getFoo method

Often the server and client output does not show up in a sequential order. In this case, the server getFoo actually completed before the client's getFooBar.

If you need to make changes to the server code, you can use webAF (without running an interactive SAS session). To do so, select File-> Remote SCL -> Open Remote SCL and then select the entry that you want to edit. The scl entry opens in an editor so that you can make your changes. In the example presented here, we added a put result=; statement to print out the value that is returned from the getFoo method. To compile the SCL entry, either click the right mouse button and select Compile or select Build->Compile File. This will save the file to the SAS catalog as well as compile it. If you need to save a file to the SAS catalog without compiling it, select File-> Remote SCL -> Save Remote SCL.

If you find that you need to terminate any remote SAS sessions initiated by webAF, you can terminate them by selecting Tools->Remove Current Remote Sessions.

You have now successfully implemented a new InformationBean with both server and client implementation. After implementation and testing are complete, you might want to JAR up the classes so that they can be used by other projects. We will use the Package Wizard to create the JAR file and then move it to the appropriate location.

Packaging an InformationBean

In order to package only the classes involved with the subclass, we will create a new project. Save and close the current project and then select File->New; Projects Tab; and the Empty Project item. Enter Custom for the project name and then click OK .

From the Insert menu, select File Into Project. Select the class entries from the custommddb project that you just created (...\webAF\Projects\custommddb\com\sas\sasserver\custom). There should be six class entries:

Select Tools -> Wizards -> Package Wizard. Deselect the options on the first dialog. Select Next to continue and add the classes that you just added to this project from the com.sas.sasserver.custom package.

If you want to sign the JAR, select Next; otherwise, select Finish.

By default, the wizard creates a JAR with the name of the project and places the JAR file in your …\webAF\Projects\custom\archive\jar directory. To include these classes as Java extension classes, move the custom.jar file to your Java extensions directory (for example, c:\jdk1.3\jre\lib\ext).

Once you have added your JAR file to the extensions library, the process of updating classes within the JAR file requires an extra step. Because webAF will be using this JAR file, you will not be able to update it while webAF is running. To add or replace a class in the JAR file, you must exit webAF. After you have updated the JAR file, you can restart webAF to access the updates.

To validate that your new classes can be found, create a new Applet Project with a multidimensionalTableView, mddbInterface and Button (as we did for the custommddb project). Set the property values for the mddbInterface to indicate the data source and query. Compile and execute the applet.

If you receive Class Not Found errors, make sure the custom.jar that you copied to the Java extensions directory includes the six classes noted previously.

Deploying Custom Classes

There are several ways to deploy your custom classes. If your classes are commonly used by many applets, then you might want to include your custom JAR file in one of your SASNetCopy configuration files. This would allow them to be automatically copied to the client machine along with other SASNetCopy classes. For additional information on SASNetCopy see the webAF online help.

For less commonly used classes, you might include the custom JAR file in the Web server directory that contains your applet JAR. Or, you might choose to include the custom classes in the applet JAR itself.

If you choose to include the custom JAR file in the Web server directory, you must manually copy the JAR file to the directory. Additionally, you must add the Archive property tag on the Environment tree node of the Project Properties window for all projects that will use the custom classes. The tag’s value should be the name of your custom JAR file.

If your custom classes will only be used by a few applets, you might want to include them in the applet’s JAR file. Rather than including the custom JAR file in the extensions directory (as described previously), add the JAR file to your system or to the classpath on the Environment tree node of the Project Properties window. In this fashion, the Package Wizard will include the custom classes in the applet’s JAR file.

Regardless of which method you choose to deploy your custom classes, you should use the Package Wizard to package your applet’s classes.

Additional Information on MultidimensionalTableInterface

There is yet another way to customize the current server implementation of the MultidimensionalTableInterface. The current server implementation has a relationship with sashelp.mddb.emddb_m.class or a subclass thereof. If you currently have subclassed this class and added customizations that you have used in the past with SAS/EIS, then you may be able to take advantage of these customizations. There are several ways that you can use your subclass rather than the default class:

Note that some subclass customizations may have no effect. The current server implementation has a subset of methods of emddb_m that it uses as its interface. If your customizations are in methods that are not used directly or indirectly by the interface, they will have no effect.The _getValues method is an example of this. For performance reasons, the current implementation uses _getBlock and not _getValues. Therefore, any customizations of _getValues would need to be added to _getBlock in order to be picked up.

Customizations to _setApplication for actions such as hiding Statistic labels and customizing the popup menus are honored as this method is part of the current interface to emddb_m.

Customizations that have been added to the viewer through the Advanced tab of an SAS/EIS application will have no effect in a thin client environment. The InformationBean communicates only with the model and has no knowledge of thick client viewers.