![]() |
![]() |
|
|
Using the Adapter Object Library
The information in this section is designed to help you learn to use the Adapter Object Library. This section contains the following information:
Creating the BVI_TuxAdapter Global Object
BroadVision runs a predetermined set of startup scripts at interaction manager startup time. The following elink.js script is one such startup script that is used to initialize the ProductName. This script is provided with the adapter and needs only to be deposited in the appropriate startup script directory.
The set of startup scripts that BroadVision runs to initialize a particular interaction manager is determined by a variable named startup-script-directories in the named interaction manager's configuration file. This configuration file shares the same name as the interaction manager it is named for and ends with a .cfg extension. Interaction manager configuration files are located in the /etc/opt/BVSNsmgr/ directory.
On startup, a given interaction manager refers to its configuration file setting for the variable called startup-script-directories. It executes all scripts found in all directories listed in this configuration file variable. To initialize the ProductName, locate the elink.js file in a directory that is listed in the startup-script-directories variable in the target interaction manager's configuration file.
The JavaScript code shown in Listing 3-1, contained in elink.js, creates a new BVI_TuxAdapter object and attaches it to the global variable called tuxAdapter. The BVI_TuxAdapter reads the configuration file whose name is passed to it as a constructor argument.
Listing 3-1 JavaScript Code
[File: elink.js]
var tuxAdapter = new BVI_TuxAdapter("/home/bvuser/bvtux.conf");
if (!tuxAdapter)
{
var log = new BVI_Log;
log.error(" Can not initialize Tuxedo Adapter");
}
The tuxAdapter variable becomes global because it is declared in the scope of a startup script. A startup script doesn't go out of scope until its interaction manager is shut down, so any variables declared in a startup script are global. The tuxAdapter variable may be referenced in any script executing in the same interaction manager.
The purpose of the BVI_TuxAdapter object is to make the adapter's configuration settings available to all of the Adapter Object Library's method calls. Only one BVI_TuxAdapter object is allocated for each running BroadVision interaction manager instance.
Creating a BVI_TuxSession Object
A BVI_TuxSession object is created for each interaction manager visitor session. The BVI_TuxAdapter object is used to create the BVI_TuxSession object. You must create this object after you create the BVI_TuxAdapter is created, but before you create any BVI_TuxService objects. Use the getNewSession method of BVI_TuxAdapter to create a new BVI_TuxSession object shown in Listing 3-2:
Listing 3-2 Sample Code for the getNewSession Method of Creating a new BVI_TuxSession Object
var tuxSession = tuxAdapter.getNewSession():
If creation of the BVI_TuxSession object fails, the errors are reported at the BVI_TuxAdapter level (in the error object member of BVI_TuxAdapter). All other errors associated with BVI_TuxSession are reported in the error object member of BVI_TuxSession. Once the BVI_TuxSession object has been created, attach it to the BroadVision session object with the code fragment shown in Listing 3-3.
Listing 3-3 Sample Code for Attaching a BVI_TuxSession Object to a BroadVision Session Object
Session.tuxSession = tuxSession;
The line of code shown in Listing 3-3 serves to make the BVI_TuxSession object lifetime identical to the BroadVision visitor's session lifetime. As BroadVision performs session tracking for the visitor, the BVI_TuxSession object follows the BroadVision session object. When a BroadVision session timeout occurs, the appropriate BVI_TuxSession object is error information collected as the BroadVision session object goes out of scope.
Creating a BVI_TuxService Object
The code sample shown in Listing 3-4 creates a new BVI_TuxService object.
Listing 3-4 Sample Code for Creating a New BVI_TuxService Object
var session = Session.tuxSession;
//If we reach this page, session is guaranteed to be valid
var service = session.getNewService("TESTSERVICE");
The service name string argument value must match a service name listed in the adapter's configuration file. If you want to make synchronous eLink Platform calls to one eLink Platform connected service only, then you need to create only one BVI_TuxService object. The execute() method is called repeatedly to affect this mode of operation.
If you want to make synchronous eLink Platform calls to more than one eLink Platform connected service, then you must create a separate BVI_TuxService object for each independent service. The execute() method may be invoked repeatedly on each service, but the service name cannot be changed on a previously allocated BVI_TuxService object.
If you want to make multiple interleaved asynchronous service calls, then you must create a separate BVI_TuxService object for each simultaneous call, even if they are all directed toward the same external eLink Platform connected service. This convention enables the adapter to independently track each call's status and error reporting state.
Creating a BVI_TuxMessage Object
The code fragment shown in Listing 3-5 allocates a new BVI_TuxMessage object.
Listing 3-5 Code for Allocating a New BVI_TuxMessage Object
var message = new BVI_TuxMessage();
You can use a given instance of BVI_TuxMessage as a request buffer repeatedly, and the instance is not allowed to go out of scope. If it does go out of scope, it is automatically collected as error information. Take care to prevent the message variable from going out of scope before the message is used as an argument to an execute() or executeAsync() method call in a BVI_TuxService object instance.
Formatting a Request Message
The code fragment shown in Listing 3-6 adds a visitor supplied request parameter to the request message.
Listing 3-6 Sample Code for Adding a Visitor Supplied Request Parameter to the Request Message
message.addLong("MSRAIRBILLNUM",Request.value("airBillVal"));
The field name for the ProductNamemust be found in the adapter's configuration file, and the value recovered from the browser's input form must be convertible to a long data type. The ProductName's field name is converted to an FML field name that must also be found in the FML configuration file. Each request parameter must be loaded into the message with an "add" call similar to the one in Listing 3-3 before the execute() or executeAsync() method is called.
Invoking a Remote eLink Platform Connected Service
The code fragment shown in Listing 3-7 synchronously executes a eLink Platform connected service.
Listing 3-7 Sample Code for Synchronously Executing a eLink Platform Connected Service
if( service.execute(message) != true) {
// Failure
}
else {
// Success
}
The message is copied into the service object on entering the execute() method. If the service invocation fails, refer to the contents of the service's error object member variable for details.
Examining a Response Message
The code fragment in Listing 3-8 lets you acquire access to the BroadVision log file, and it allocates a response value variable called resval. It then writes the list element name to the visitor's browser and recovers an AIRBILLNUMBER from the response message (service.output). If the recovery of the long value from the response message is successful, the value is written to the visitor's browser. Otherwise, error information from the response message is output to the BroadVision log file.
Listing 3-8 Sample Code for Examining the Response Message
var log = new BVI_Log;
BVI_Value resval;
Response.write("<Li>Air Bill Number  " );
if(service.output.getLongDef("AIRBILLNUMBER", 0,
resval, 99.99) == true) {
Response.write(resval.longValue);
}
else {
log.error(" getLongDef failed. FieldName: " + "AIRBILLNUMBER");
log.error("ErrorType: " + service.output.error.errorType +
"ErrorCode: " + service.output.error.errorCode + "Error Message: "+
service.output.error.Message);
Response.write(" Not Available" );
}
Each value returned in the response message should be recovered in a similar fashion to the example above.
Invoking a Remote eLink Platform Connected Service Asynchronously
eLink Platform services may be called asynchronously from BroadVision applications that have other work to do while the externally connected eLink Platform application is responding to the request. The annotated example shown in Listing 3-9 is provided to give you an example of how this may be accomplished. This example breaks the processing into two parts: a request script and a response checking/display script. The request script issues the service request. The response checking/display script checks for a response, and if it finds that one is ready, displays it.
If the response checking/display script determines that the response is not ready, it prompts the BroadVision visitor with a link that reruns the script. The visitor keeps running the script until a response is ready. The benefit of this approach is that it affords the BroadVision application developer the ability to substitute any useful processing in the delay between issuing the request and obtaining a response. Once the response is present, it remains queued until the application gets around to picking it up.
Listing 3-9 Sample Code for Calling a eLink Platform Service Asynchronously
[executeasync.jsp]
<%
var log = new BVI_Log;
// Acquire access to the previously created BVI_TuxSession object
var session = Session.tuxSession;
// Create a BVI_TuxService object for the service of interest
var service = session.getNewService("TESTSERVICE");
if(service != null)
{ // The BVI_TuxService object was successfully created
var message = new BVI_TuxMessage();
// Populate a new request message with the request parameters
message.addLong("MSRAIRBILLNUM",Request.value("airBillVal"));
// Use the asynchronous form of service execution
if( service.executeAsync(message) != false)
{ // Attach the new BVI_TuxSession object to the
// BroadVision session object, so that the response
// checking/display script has access to it.
Session.myService = service;
// Display the link for the response checking/display
// script.
%><A HREF="<%=makeScriptURL('/broadway/scripts/tuxedo/getreply.jsp')%>" >
<b><font face="arial,helvetica" size="-1">
Get Reply</font></b></A>
<%
}
else//service.executeAsync(message) == false
{
// The executeAsync(message) method failed
// Begin error handler
if(service.error != null)
{
// The error will be reported in the BVI_TuxService
// object's error member object.
if(service.error.errorType == TUX_TUX_ERROR)
{
Response.write(" <BR> ****Internal Error*** Can not retrieve data for AirBill Number: " + Request.value("airBillVal") );
log.error("Tuxedo error encountered while calling TESTSERVICE");
log.error("ErrorCode: " + service.error.errorCode + "Error Message: " + service.error.Message);
}
else//service.error.errorType == TUX_ADAPTER_ERROR
{
Response.write(" <BR> ****Internal Error*** Can not retrieve data for AirBill Number: " + Request.value("airBillVal") );
log.error("Adapter error encountered while calling TESTSERVICE");
log.error("ErrorCode: " + service.error.errorCode + "Error Message: " + service.error.Message);
}
}
else
{
// The BVI_TuxService's error member object wasn't
// present. If this log entry is made, it indicates that
// the Adapter Object Library has an internal design
// flaw. We shouldn't be able to get here.
log.error("service.error NULL");
}
}
}
else
{
// This error handler is for catching a failure to
// create the necessary BVI_TuxService object.
Response.write(" <BR> ****Internal Error*** Can not instantiate service object");
log.error("session.getNewService failed");
// The potential error can be of type TUX_TUX_ERROR and
// TUX_ADAPTER_ERROR
// log.error("ErrorType: " + session.error.errorType + "ErrorCode: " + session.error.errorCode + "Error Message: " + session.error.Message);
}
%>
The only work that remains for this example is to review the code for response checking/display.
[getreply.jsp]
<%
// In order to check for a response, the BVI_TuxService object
// is retrieved from the BroadVision session object.
var service = Session.myService;
var log = new BVI_Log;
if(service == null)
{
// Recovery from not finding the BVI_TuxService object
Response.write(" Unable to get the Service Info <BR> ");
log.error("Unable to get the Service Info");
}
else
{
// The BVI_TuxService object was found - look for the response
if(service.getReply() != false)
{
// The response is present - now display it.
// Allocate a BVI_Value to receive each successive field
// from the response message.
var resval = new BVI_Value;
// Format your HTML output however you like.
Response.write("<Li>Air Bill Number  " );
// Get a long AIRBILLNUMBER from the response into resval
if( service.output.getLongDef("AIRBILLNUMBER", 0, resval, 15.54) == true)
{
// Output the long AIRBILLNUMBER to the browser
Response.write(resval.longValue);
}
else
{
// Recover from not finding the AIRBILLNUMBER in the
// response message.
log.error(" getLongDef failed. FieldName: " + "AIRBILLNUMBER");
log.error("ErrorType: " + service.output.error.errorType + "ErrorCode: " + service.output.error.errorCode + "Error Message: " + service.output.error.Message);
Response.write(" Not available" );
}
// Display the next response field
Response.write("<Li>Flight Carrier " );
if( service.output.getStringDef("FCARRIER", 0, resval, "fcarrier") == true)
{
Response.write(resval.stringValue);
}
else
{
log.error(" getStringDef failed. FieldName: " + "FCARRIER");
log.error("ErrorType: " + service.output.error.errorType + "ErrorCode: " + service.output.error.errorCode + "Error Message: " + service.output.error.Message);
Response.write(" Not available" );
}
Response.write("<Li> Flight " );
if( service.output.getStringDef("FLIGHT", 0, resval, "flight") == true)
{
Response.write(resval.stringValue);
}
else
{
log.error(" getStringDef failed. FieldName: " + "FLIGHT");
log.error("ErrorType: " + service.output.error.errorType + "ErrorCode: " + service.output.error.errorCode + "Error Message: " + service.output.error.Message);
Response.write("Not available" );
}
// Process the remaining fields in the response
// Display the last response field
Response.write(" <Li> Note ");
if( service.output.getStringDef("NOTE", 0, resval, "note") == true)
{
Response.write(resval.stringValue);
}
else
{
log.error(" getStringDef failed. FieldName: " + "NOTE");
log.error("ErrorType: " + service.output.error.errorType + "ErrorCode: " + service.output.error.errorCode + "Error Message: " + service.output.error.Message);
Response.write(" Not available" );
}
Response.write("</ul>" );
// The Display section is completed.
// Now overwrite the BroadVision session object's
// reference to the BVI_TuxService object, causing it to
// be garbage collected.
Session.myService = null;
}
else
{
// An error has occurred - Perform error recovery
if(service.error != null)
{
if(service.error.errorType == TUX_APPLICATION_ERROR)
{
// Application level error.
// The externally connected Tuxedo Application
// cannot process the request.
// Display the error to the visitor.
Response.write(" <BR> Can not retrieve data for AirBill Number: " + Request.value("airBillVal") );
var errorMessage = new BVI_Value;
// Get the application error message out of the
// response message and display it.
service.output.getStringDef("APPERROR", 0, errorMessage, "DEFAULT");
Response.write(" ErrorCode: " + service.error.errorCode + "Error Message: " + errorMessage.stringValue );
log.error("ErrorCode: " + service.error.errorCode + "Error Message: " + errorMessage.stringValue);
}
else if(service.error.errorType == TUX_TUX_ERROR)
{
// A Tuxedo Error has occurred
// Check to see if the response is present yet
if(service.error.errorCode == TPEBLOCK)
{
// The response is not available yet.
// Give the visitor a link to try again.
%>
The service <B><I><%=service.serviceName%></I></B> has not yet returned.
<BR> Please try again..
<A HREF="<%=makeScriptURL('/broadway/scripts/tuxedo/getreply.jsp')%>"> Get Reply Again </A>
<%
}
else
{// Some other Tuxedo error has occurred
Response.write(" <BR> ****Internal Error*** Can not retrieve data for AirBill Number: " + Request.value("airBillVal") );
log.error("Tuxedo error encountered while getReply TESTSERVICE");
log.error("ErrorCode: " + service.error.errorCode + "Error Message: " + service.error.Message);
}
}
else//service.error.errorType == TUX_ADAPTER_ERROR
{// An adapter error has occurred
Response.write(" <BR> ****Internal Error*** Can not retrieve data for AirBill Number: " + Request.value("airBillVal") );
log.error("Adapter error encountered while calling TESTSERVICE");
log.error("ErrorCode: " + service.error.errorCode + "Error Message: " + service.error.Message);
}
}// The service object should have an error object
// at this point - no recovery required
} // End of error recovery
} // End of BVI_TuxService object present
%>
%>
This concludes the asynchronous service execution example. Both the BVI_TuxService::executeAsync() and BVI_TuxService::getReply() methods are nonblocking, allowing you to do additional work for the BroadVision visitor while the called eLink Platform service is responding to the request.
Invoking Multiple Services Simultaneously
The example shown in Listing 3-9 indicates how additional work may be accomplished during the course of waiting for a response from an externally connected eLink Platform application. Suppose you want to interleave additional eLink Platform service requests in this waiting period. This is done very simply by instantiating multiple BVI_TuxService objects, one for each simultaneous call. They may each reference the same or different services defined in the eLink Adapter for BroadVision configuration file.
Invoke the BVI_TuxService::executeAsync() method on each of the instantiated BVI_TuxService objects interleaved with BVI_TuxService::getReply() calls in any sequence you desire. Refer to the multiexecuteasync.jsp file in the eLink Adapter for BroadVision software distribution for an example of how to invoke multiple services simultaneously.
Cleanup Considerations
The eLink Platform client environment is initialized and connected to the eLink Platform bulletin board when the BVI_TuxAdapter is instantiated, within the elink.js startup script. BVI_TuxSession objects are created and attached to the BroadVision session object for each visitor session. Then, as visitors exercise pages that invoke eLink Platform transactions, BVI_TuxService and BVI_TuxMessage objects are created.
The BVI_TuxMessage objects are destroyed when the JavaScript variables referencing them go out of scope. BVI_TuxService objects are destroyed similarly, unless they have also been attached to the corresponding BroadVision session object.
The objects attached to a given BroadVision session object (BVI_TuxSession and sometimes BVI_TuxService) are destroyed when the BroadVision session timesout. The BVI_TuxAdapter disconnects the Interaction Manager from the eLink Platform environment when the Interaction Manager is shutdown, and the BVI_TuxAdapter is automatically destroyed.
As such, no explicit cleanup code need be authored by the BroadVision developer to prevent memory leaks or regulate access to the eLink Platform environment.
If the eLink Platform environment is cycled for maintenance purposes, then the associated BroadVision Interaction Managers must also be cycled in order for the Interaction Managers to reconnect to the eLink Platform environment.
Adding a New Service
New services are simple to add to a running BroadVision application. To add a new service:
This method causes the configuration file to be read into memory, so that the updated version of it becomes available to existing instances of BVI_TuxService and BVI_TuxMessage objects. This Interaction Manager prevents adverse race condition side affects that might otherwise create issues with using this approach.
Care must be taken to not remove any service or field definitions from the configuration file for services and fields in current use. This methodology only applies to "adding" services and their field definitions.
![]() |
![]() |
![]() |
|
Copyright © 2000 BEA Systems, Inc. All rights reserved.
|