Troubleshooting a distributed PowerBuilder application
Testing locally
Like a traditional PowerBuilder application,
a distributed PowerBuilder application can be tested on a single
computer. You can test your application by running it in a single
process, either in test mode or debug mode, or by running a single
executable (EXE) file. Alternatively, you can test the client and
server applications in separate processes, where at least one is
an executable file.
Using the Local driver
PowerBuilder provides a Local driver that lets you test a distributed
application without having to use one of the standard communications
protocols. This allows you to test a large part of your work without
being concerned with the network configuration on which the application
will be deployed. You can use the Local driver on all platforms.
One of the biggest
advantages of testing applications with the Local driver is that
this approach allows you to use the PowerBuilder debugger to identify problems
in your code. When you run an application in a distributed environment,
you cannot use the debugger to examine the behavior of the server
application.
Using the trace facility
PowerBuilder provides
a trace facility to help you identify and fix problems that may
arise once an application is running in a distributed environment.
The trace options allow you to monitor client/server communications
by logging system activity to a console window or to a file. You
can use the trace facility in both the client and server applications.
Testing with the Localdriver
If you want to use the
debugger to identify problems in both the client and server components
of a distributed application, you need to test the application with
the Local driver.
Local driver not supported with Version 7 Proxy objects You cannot use the Local driver to test a distributed application
if you have Version 7 Proxy objects in the library list for the
application.
No Transport object required
When you test an application with the Local driver, PowerBuilder handles
all requests for remote services by emulating the server. Because PowerBuilder takes
care of all communications functions normally handled by the Transport object,
the application does not have to create a Transport object or perform any
of the activities associated with using the Transport object.
Local driver uses a single process
When you use the Local driver, your application runs in a
single process. This restricts the client and server components
of your application to the same variable context and name space,
which may lead to usage conflicts.
Example
The following script shows how to establish a client connection
by using the Local driver. The script instantiates the myconnect
Connection object and sets the Driver property of the Connection
object to identify the Local driver. Then the script invokes the
ConnectToServer function to establish the connection. Notice that
the script does not set the Application and Location properties
of the Connection object; these properties are not required with
the Local driver:
1 |
// Global variable: |
1 |
// connection myconnect |
1 |
1 |
long ll_rc |
1 |
myconnect = create connection |
1 |
myconnect.driver = "Local" |
1 |
myconnect.application = "" |
1 |
myconnect.location = "" |
1 |
ll_rc = myconnect.ConnectToServer() |
1 |
IF ll_rc <> 0 THEN |
1 |
MessageBox("Connection failed", ll_rc) |
1 |
END IF |
Running the debugger
When you test a distributed
application with the Local driver, you have access to the full range
of debugging features available with PowerBuilder. You can set stops
(breakpoints) in scripts, step through the code line by line, and
display the contents of variables. When you run your application
in debug mode, PowerBuilder stops execution just before it hits a
line containing a stop. You can then look at (and change) the values
of variables.
For more information about running in debug
mode, see the PowerBuilder User’s Guide
.
Testing locally witha communications driver
You can
test a distributed application on a single computer with any of
the supported communications drivers. You can test the application
in a single process or run separate processes for the client and
server components.
NamedPipes driver
To test locally with the NamedPipes driver, you need a Windows NT machine. Server
support is not provided for this driver on other platforms.
Example
The following script establishes a client connection to a
server application that is available locally. This example uses
the WinSock driver. To tell PowerBuilder to service requests locally,
the client sets the Location property to Localhost:
1 |
// Global variable: |
1 |
// connection myconnect |
1 |
long ll_rc |
1 |
1 |
myconnect = create connection |
1 |
myconnect.driver = "WinSock" |
1 |
myconnect.application = "myapp" |
1 |
myconnect.location = "Localhost" |
1 |
ll_rc = myconnect.ConnectToServer() |
1 |
IF ll_rc <> 0 THEN |
1 |
MessageBox("Connection failed", ll_rc) |
1 |
END IF |
For this example to work, the TCP/IP hosts file on
the test machine would need to include an entry for localhost:
1 |
127.0.0.1 localhost |
In addition, the TCP/IP services file on the test
machine would need to include an entry for the myapp application
service:
1 |
myapp 10015/tcp |
Using the trace facility
PowerBuilder provides
several trace options to help you identify and fix problems that
may arise once an application is running in a distributed environment.
The trace options allow you to monitor client/server communications
by logging system activity to a console window or to a file.
The trace facility is available to both the client and server
components of a distributed PowerBuilder application. You can use
the trace facility to monitor system activity on either the client
or the server, or you can monitor activity on both the client and
the server simultaneously. The trace facility does not work with
Jaguar components.
Specifying trace options
To use the trace facility,
you need to assign a value to the Trace property of either the Connection
object on the client or the Transport object on the server.
Trace option keywords
The value you assign can specify one or more of the trace
option keywords:
Trace option | Description |
---|---|
All=1 | Logs all activity against the server. This option logs internal information that can be helpful in debugging, including memory usage, an internal call trace, and the types and values for passed parameters |
Console=1 | Logs activity to a console window |
DumpArgs=1 | Logs parameter types and values |
Level=1 | Enables Console=1, ObjectCalls=1, ObjectLife=1, and WebPB=1 |
Log=filename | Logs activity to the specified file. If the server application uses multiple Transport objects, you need to specify a unique log file name for each Transport object |
ObjectCalls=1 | Logs each object method call and indicates whether the call was successful |
ObjectLife=1 | Logs each attempt to create or destroy a remote object and indicates whether the operation was successful |
WebPB=1 | Logs all Web.PB activity against the server application (Transport object only) |
If you specify more than one keyword, the keywords must be
separated by commas.
Examples
This example sets the trace option for the Transport object
on the server to log each attempt to create or destroy an object,
or call one of its methods. The output displays in a console window
on the server machine:
1 |
mytransport.trace="Level=1" |
This example sets the trace option for the Transport object
to log each attempt to create or destroy an object. The output displays
in a console window on the server machine:
1 |
mytransport.trace="Console=1,ObjectLife=1" |
This example sets the trace option for the Connection object
to log each call to an object method. The output is logged to a
file on the client machine.
On Windows:
1 |
myconnect.trace="log='c:mylog.log',ObjectCalls=1" |
On UNIX:
1 |
myconnect.trace="log='/dir/mylog.log',ObjectCalls=1" |
Viewing the trace output
This section shows sample output for several of the trace
options.
Example 1: ObjectCalls=1
This example shows trace output you might see on a server
when the ObjectCalls=1 option is enabled. The log indicates
that a client connected to the server, created an instance of a
remote object, and called a function f_myfunc, which takes
a single argument:
1 |
DPB40 SessionId (00000000): Handle Request: CREATE_SESSION(1), streamVer(0). SUCCEEDED (00000000) |
1 |
DPB41 : Use Session : sessionId(28072544). SUCCEEDED (00000000) |
1 |
DPB40 SessionId (01AC5A60): Handle Request: CREATE_INSTANCE(3), streamVer(0). SUCCEEDED (00000000) |
1 |
DPB40 SessionId (01AC5A60): Handle Request: INVOKE(6), streamVer(0). SUCCEEDED (00000000) |
1 |
DPB48 SessionId (01AC5A60): Invoke : instanceId(00000008), f_myfunc(SS), numArgs(1) SYNCHRONOUS |
1 |
DPB40 SessionId (01AC5A60): Handle Request: RELEASE_INSTANCE(5), streamVer(0). SUCCEEDED (00000000) |
Example 2: All=1
This example shows trace output you might see on the client
when the All=1 option is enabled. The log indicates that
the client made an asynchronous call to a function called f_double
that takes two arguments. The first argument is a long value that
specifies the number that the function will double. The second is
an object of type nvo_response_object. The object
reference provides the server with a way to push a response back
to the client. To send a message back to the client, the server
calls the notify_client function:
1 |
SMI AddRef SMI_TRACE(01AC53F0) refCount(4) |
1 |
DPB AddRef DPB_MARSHALING(01AC6318) refCount(1) |
1 |
DPB AddRef DPB_MARSHALING(01AC6318) refCount(2) |
1 |
DPB Release DPB_MARSHALING(01AC6318) refCount(1) |
1 |
SMI01 Connection(01AC52E0): Create Message: (01AC59B0), initial size 0 bytes |
1 |
Write Invoke Request: 12.f_double(QLCnvo_response_object.) |
1 |
Write LONG: value(50) |
1 |
Write Object Reference: class(nvo_response_object), asClass(nvo_response_object), id(21), session(28061624) |
1 |
DPB48 SessionId (01AC5A18): Invoke : instanceId(0000000C), f_double(QLCnvo_response_object.), numArgs(2) ASYNCHRONOUS |
1 |
SMI03 Connection(01AC52E0): Send Message: (01AC59B0) sequenceNumber(20) Asynchronous. ... (00000000) |
1 |
WSD07 ReadHeader: Proto = 24576, Len = 177 |
1 |
WSD08 Send: result = 0 |
1 |
SMI01 Connection(01AC52E0): Create Message: (01AC66F8), initial size 177 bytes |
1 |
SMI03 Connection(01AC52E0): Send Message: (01AC59B0) sequenceNumber(20) Asynchronous. SUCCEEDED (00000000) |
1 |
DPB AddRef DPB_SESSION_SERVICE(01AC5438) refCount(2) |
1 |
DPB Release DPB_MARSHALING(01AC6318) refCount(0) |
1 |
DPB40 SessionId (01AC2FB8): Handle Request: INVOKE_ASYNC(7), streamVer(0). SUCCEEDED (00000000) |
1 |
DPB AddRef DPB_SESSION_SERVICE(01AC5438) refCount(3) |
1 |
SMI Release SMI_TRACE(01AC53F0) refCount(3) |
1 |
DPB Release DPB_SESSION_SERVICE(01AC5438) refCount(2) |
1 |
SMI06 Connection(01AC52E0): Process request Message: (01AC66F8) serviceId(0), sequenceNumber(25). SUCCEEDED (00000000) |
1 |
WSD07 ReadHeader: Proto = 24576, Len = 141 |
1 |
SMI AddRef SMI_TRACE(01AC53F0) refCount(4) |
1 |
SMI01 Connection(01AC52E0): Create Message: (01AC59B0), initial size 141 bytes |
1 |
DPB AddRef DPB_SESSION_SERVICE(01AC5438) refCount(3) |
1 |
DPB AddRef DPB_MARSHALING(01AC6318) refCount(1) |
1 |
DPB40 SessionId (01AC2FB8): Handle Request: RELEASE_INSTANCE(5), streamVer(0). SUCCEEDED (00000000) |
1 |
DPB AddRef DPB_SESSION_SERVICE(01AC5438) refCount(4) |
1 |
DPB AddRef DPB_MARSHALING(01AC6318) refCount(2) |
1 |
DPB Release DPB_SESSION_SERVICE(01AC5438) refCount(3) |
1 |
SMI06 Connection(01AC52E0): Process request Message: (01AC59B0) serviceId(0), sequenceNumber(27). SUCCEEDED (00000000) |
1 |
Read Invoke Request: 21.notify_client(QS) |
1 |
Read STRING: value(100) |
1 |
DPB48 SessionId (01AC2FB8): Invoke : instanceId(00000015), notify_client(QS), numArgs(1) ASYNCHRONOUS |
1 |
SUCCEEDED (00000000) |
1 |
DPB Release DPB_MARSHALING(01AC6318) refCount(1) |
1 |
DPB Release DPB_MARSHALING(01AC6318) refCount(0) |
1 |
SMI Release SMI_TRACE(01AC53F0) refCount(3) |
1 |
DPB55 Memory Session : (01AC5438) count(6683), total(2322432), alloc(1038398), free(1185706) |
1 |
DPB56 Memory Proc Common : count(656), total(102400), alloc(42402), free(55107) |
1 |
DPB Release DPB_SESSION_SERVICE(01AC5438) refCount(2) |
1 |
SMI AddRef SMI_TRACE(01AC53F0) refCount(4) |
1 |
DPB AddRef DPB_MARSHALING(01AC6318) refCount(1) |
1 |
DPB AddRef DPB_MARSHALING(01AC6318) refCount(2) |
1 |
Read Release Request: 21 |
1 |
DPB45 SessionId (01AC2FB8): Release Object: instanceId(00000015) |
1 |
SUCCEEDED (00000000) |
1 |
SMI01 Connection(01AC52E0): Create Message: (01AC66F8), initial size 0 bytes |
1 |
SMI03 Connection(01AC52E0): Send Reply Message: (01AC66F8) sequenceNumber(27) Asynchronous. ... (00000000) |
1 |
WSD08 Send: result = 0 |
1 |
SMI03 Connection(01AC52E0): Send Reply Message: (01AC66F8) sequenceNumber(27) Asynchronous. SUCCEEDED (00000000) |
1 |
DPB49 SessionId (01AC2FB8): Send Result : SUCCEEDED (00000000) |
1 |
DPB Release DPB_MARSHALING(01AC6318) refCount(1) |
1 |
DPB Release DPB_MARSHALING(01AC6318) refCount(0) |
1 |
SMI Release SMI_TRACE(01AC53F0) refCount(3) |
1 |
DPB55 Memory Session : (01AC5438) count(6682), total(2322432), alloc(1038383), free(1185721) |
1 |
DPB56 Memory Proc Common : count(629), total(102400), alloc(29136), free(68378)DPB Release DPB_SESSION_SERVICE(01AC5438) refCount(1) |
A collection of techniques you can use to implement general
features in the applications you develop with PowerBuilder. Includes
printing from an application, developing for multiple platforms,
and internationalizing an application.