Developer's-Panther WebSphere


Chapter 7. Building Client Screens

This chapter describes how client screens in your Panther application can access Enterprise JavaBeans. A series of C functions, also callable in JPL and through Panther's Java interface, are available for interacting with all Panther service components.


Creating Client Screens

Client screens are the part of the application accessed by users. They can include fields for data, push buttons for performing actions, selection groups for assembling options, option menus for listing choices. These and other user interface options are described in Using the Editors.

Refer to "Creating a New Screen" in Using the Editors for steps on creating a new screen.


Specifying the WebSphere Server

You need to specify the machine running WebSphere. At runtime, the value is derived from the provider_url application property. If the SMPROVIDERURL environment variable is set, this property is initialized with this value. However, you can also set this property programmatically. List the server machine's host name and port number (iiop://hostName:portNumber).

If you specify the value in JPL, remember to use double colons. For example, the following JPL command would set the property back to its default value:

@app()->provider_url="iiop:://localhost::900"

Specifying the Component System

Before instantiating a component, you must first specify which type of service components are currently in use with the current_component_system property: PV_SERVER_EJB for EJBs or PV_SERVER_COM for COM components.


Instantiating an EJB

After the component system is specified, you instantiate a component by calling sm_obj_create. It takes a string parameter, the name of the component.

This function returns an object ID for the specified component or PR_E_OBJECT if it fails. Using this object ID, you can access the component's properties and methods.

Sample Component Horoscope

In the horoscope sample, when a user submits the screen, the following JPL procedure specifies the component system and instantiates the EJB:

proc submit()
{
vars id,res

@app()->current_component_system = PV_SERVER_EJB
id = sm_obj_create("fortuneEJB")
if (id<=0)
{
msg emsg "Can't create EJB"
return
}
res = sm_obj_call \
(id,"newFortune",birthdayText,resultTextBox)
if (res<0)
msg emsg "Method failed"

call sm_obj_delete_id(id)
return
}

Destroying EJB Components

After invoking and working with the methods or properties of a component, you should destroy the component by calling sm_obj_delete_id. This function takes one parameter: the object ID for the component you wish to destroy. Otherwise, the component will continue to exist until the application terminates (or goes from test to edit mode).


Accessing the Component's Methods

To access EJB methods, you need to know the component's parameters and call the function sm_obj_call. The syntax in JPL is as follows:

ret = sm_obj_call (objid, methodName, parm1, parm2, ....)

The function's first parameter objid is the object ID of the component whose method you wish to use. The second parameter methodName is the name of the method you are calling. The rest of the parameters (parm1, parm2, ....) are a comma-separated list of the parameters to the method itself.

Specifying the Method's Parameters

EJBs can take three kinds of parameters: in parameters, out parameters and in/out parameters. Parameters can be passed as literal strings or using the property API syntax. For out and in/out parameters, Panther assigns the returning values to the variables, fields or properties originally specified.

Sample Component Employee

For example, a component called Employee supports a method called NewEmployee, which takes three parameters in the following order:

You can invoke NewEmployee method with the following JPL:

vars id, ret
@app()->current_component_system=PV_SERVER_EJB

id = sm_obj_create ("Employee")

ret = sm_obj_call (id, "NewEmployee", \
EmpId, Emanate, StartDate)

In addition to the out parameters, this method call returns a value. ret contains the return value for the method.


Accessing the Component's Properties

Properties in EJBs can contain application state information. You can use the sm_obj_set_property and sm_obj_get_property functions to access properties. The following example sets a property on the component associated with the id variable:

ret = sm_obj_set_property(id, "PropName", "PropSetting")

Designating an Error Handler

You can define an error handler for method invocations, such as in the following example:

call sm_obj_onerror ("ErrorHandlerName")

The string passed to sm_obj_onerror is the name of a function that you want to designate as the error handler. If an operation (method call, property access, or object invocation) generates a negative exception code, the error handler function is called. The specified function is passed three parameters: the error number in decimal format, the error number in hexadecimal format, and a description of the error.

(On the server side, methods can also return exception codes using the JPL verb raise_exception or its C equivalent sm_raise_exception.)


Writing a Java Event Handler

Instead of using JPL, you can use Java to implement the client processing. In the screen's Java Tag property, enter the name of the screen's Java event handler.

For more information about Java event handlers, refer to Chapter 21, "Java Event Handlers and Objects," in the Application Development Guide.

Sample Java Event Handler: Client Screen

In the following sample which instantiates and destroys the component, the client screen calling this event handler has a Java Tag of ClientScreen.

import com.prolifics.jni.*;

public class ClientScreen extends ScreenHandlerAdapter{

public void screenEntry(ScreenInterface s, int context){
FieldInterface id = s.getField("id");
FieldInterface id1=s.getField("id1");
CFunctionsInterface cFuncs = s.getCFunctions();
ApplicationInterface appface=s.getApplication();
ScreenInterface tscr=appface.getScreen();
int a=appface.set_int
(Constants.PR_CURRENT_COMPONENT_SYSTEM,
Constants.PV_SERVER_EJB);
id1.itofield(a);
id.itofield(cFuncs.sm_obj_create("cStrings"));
}

public void screenExit(ScreenInterface s, int context){
CFunctionsInterface cFuncs = s.getCFunctions();
FieldInterface id = s.getField("id");
cFuncs.sm_obj_delete_id(id.intval());

Sample Java Event Handler: Push Button

On this client screen, a button event handler for the Search push button calls the method and gets the number of returned rows. The push button calling this event handler has a Java Tag of SearchButtonHandler.

import com.prolifics.jni.*;

public class SearchButtonHandler extends ButtonHandlerAdapter{

public int buttonValidate
(FieldInterface f, int item, int context){
ScreenInterface s = f.getScreen();
FieldInterface idField = s.getField("id");
FieldInterface rowField = s.getField("RowCount");
FieldInterface searchField = s.getField("search");
FieldInterface
companyNameField = s.getField("CompanyName");
CFunctionsInterface cFuncs = f.getCFunctions();

companyNameField.putfield(1,searchField.getfield());
int id = idField.intval();
String i = cFuncs.sm_obj_call("(" + id + ",
'GetCustomer',CompanyName,CustomerID,Phone)");
String st = cFuncs.sm_obj_get_property
( id, "RowCount");
rowField.putfield(st);
return id;
}
}

Saving Client Screens

Client screens are stored in an application library available to the client executable. The default name of the application library is client.lib.

Refer to "Saving an Application Component" in Using the Editors for information about saving screens to application libraries.


Sample Client Screen

Although simple in appearance, this screen contains the fields and push buttons needed to operate the client part of an application and illustrates the concepts described in this chapter.

However, apart from the component system specification, nothing in the client interface indicates that it is calling an Enterprise JavaBean. In fact, the same code could be used to call a COM component. The component system specification determines which type of component gets instantiated.

Figure 7-1 This client screen allows users to look up company names and telephone numbers.

Sample Component: Customer

The unnamed JPL procedure creates the variable which will hold the object ID of the EJB. During screen entry, the EJB is instantiated.

vars id

proc enter
{
@app()->current_component_system=PV_SERVER_EJB
id = sm_obj_create("Customers")
}

On exiting the screen, the EJB is destroyed.

proc exit
{
call sm_obj_delete_id(id)
}

This JPL procedure calls the EJB's GetCustomer method and gets the value of the RowCount property:

proc do_search
{
vars error
CompanyName[1] = search
error = sm_obj_call (id, "GetCustomer", \
CompanyName, CustomerID, Phone)
rowcount = sm_obj_get_property (id, "RowCount")
}

The Panther distribution contains additional EJB samples. For a full description, refer to Appendix B, "Sample Applications."