Building a distributed application
Building the DPB Server

In this section and the next we'll see how to partition the monolith application into Client and Server components. In the development environment you need not have two machines to do this. You can run the client and server applications on the same machine. Eventually when your distributed application has been tested and is ready for the  production environment, you will want to run the server application on a dedicated machine and deploy you client application to your user machines.

On the server side we need to accomplish the following -

  1. Create a DPB server application that can host NVOs and serve client applications.
  2. Separate the remote objects from the monolith application and host them on this server

It's important to note that the server application is not tied to the objects that it hosts. Think of it as just a container for NVOs. In fact, it's a good strategy to build a generic server application that's independent of the objects it is hosting. With this approach you can easily serve more that one, different PowerBuilder client applications. You can even use a server that somebody else has built. In a later section I have mentioned the DPB server built by PowerObjects which is freely available to everyone. This server provides a lot of great functionality like tracing, status, a remote console etc. All you have to do is provide the objects to be hosted.

We'll go ahead with building a basic server anyway since it will help you understand the fundamentals of hosting NVOs in a DPB server.

 

Building the Server application

The  server application that we are going to build is going to be a simple one. All that it's going to do is open a console window and start listening for client connections. The code for this server can be found in pbserver.pbl. This PBL contains two objects - a application object called 'pbserver' and the console window 'w_console'.

The open event of the application object just opens the console window -

pbserver::open

Open(w_console)

The code to connect to the database is not coded in the open event. Why? To understand this, it is necessary to understand the concept of a 'session'. Each client application that will connect to this server will run in it's own, separate thread. It will have it's own copy of the global variables, which includes SQLCA. The server itself runs in its own separate session. It is the server session that will execute the open event of the application and open the console window. As a result, the SQLCA of the server is not available to any client connections. So where do you put the initialization and clean up code for a client? You do it in the 'ConnectionBegin' and 'ConnectionEnd' events. And that's where we'll move the database connect and disconnect code -

pbserver::connectionbegin

// Profile Powersoft Demo DB V6
SQLCA.DBMS = "ODBC"
SQLCA.Database = "Powersoft Demo DB V6"
SQLCA.AutoCommit = False
SQLCA.DBParm = "ConnectString='DSN=Powersoft Demo DB V6;UID=dba;PWD=sql'"

connect;

//Allow the user to connect with normal privileges
ConnectPrivilege access_rights
access_rights = ConnectPrivilege!

Return access_rights

pbserver::connectionend

disconnect;

Note: Here the server presumes which database all client applications will want the server to connect to. This may not be acceptable in a real life application. When you want to control the database to which the server connects to, you can use the 'connectstring' property of the ConnectionObject used by the client application. The value passed in this property becomes available as the 'connectstring' argument in the connectionbegin event at the server.

 

The Console Window

The console window consists of a couple of buttons for starting and stopping the server. There's also a static text object which will be used to display the status of the server. A DPB application listens for client connections using a 'transport' object. The w_console window defines an instance variable 'itrp_Transport' of this type. This instance is created and destroyed in the Open and Close events of the window respectively.

w_console::open

// Create the transport object
itrp_Transport = Create Transport

w_console::close

// Destroy the transport object
Destroy itrp_Transport

The code in the Clicked event of the Start button initializes the properties of the transport object and calls the Listen() function on it to start listening for client connections. This server listens to client connections using the WinSock driver which operates on a TCP/IP network. DPB supports other drivers but WinSock is by far the preferred driver due to the popularity of TCP/IP.

w_console.cb_start::clicked

SetPointer(HourGlass!)

itrp_Transport.Driver = "WinSock"
itrp_Transport.Application = "pbserver"

// Start listening for client connections
itrp_Transport.Listen()

If itrp_Transport.ErrCode = 0 Then
    st_status.Text = "Server Running"
Else
    st_status.Text = String(itrp_Transport.ErrCode) + " - " + itrp_Transport.ErrText
End If

This.Enabled = False
cb_stop.Enabled = True

Finally, the code in the Clicked event of the Stop button stops the transport object from listening using the StopListening() method-

w_console.cb_stop::clicked

itrp_Transport.StopListening()

If itrp_Transport.ErrCode = 0 Then
    st_status.Text = "Server Stoped"
Else
    st_status.Text = String(itrp_Transport.ErrCode) + " - " + itrp_Transport.ErrText
End If

This.Enabled = False
cb_start.Enabled = True

 

That's all that there is to it. Well, almost. All the PowerBuilder coding for the server is done, but we still need to configure the TCP/IP setup. We need to specify the TCP/IP port on which our DPB server will be listening for client connections. This is similar to other TCP/IP ports that you might be familiar with, for example if you are setting up a webserver like MS IIS or O'rielly Website, you will typically assign port 80 to the server to listen to HTTP requests from browsers. Databases like SQL Server have designated ports for SQL requests. Here's how it's done -

  1. Check if TCP/IP is installed on your machine. On Windows 95 and Windows NT, this can be done by checking the installed protocols in Control Panel - NetWork - Configuration.
  2. Open a file called 'services' found in the Windows directory using a text editor like Notepad. This file specifies what services are available at which port on this machine.
  3. The format for specifying a service is -
    <service name> <port number>/<protocol> [#<comment>]
  4. We'll specify our DPB server as a service here. The service name should be same as the value provided for the 'Application'  property of the transport object. In our case it's 'pbserver'. The port number we specify should be unique in order to avoid conflict. You can use the next available port in your services file. Here's what the entry looks like -
    pbserver    10013/tcp        #DPB Server

We are all done. Run the server application and test if it can start and stop successfully.

 

Separating Remote Objects

This is where the real partitioning begins. We start the process by separating the objects from the monolith that we want to host on our DPB server. The list of objects that are to be hosted remotely should be fairly obvious if you went through the design phase earnestly (yeah, there are developers who still believe that designing is for wimps and that macho programmers like themselves just hit the keyboard and figure it out as they go along). In our case it's the nvo_employee object. We'll move it from pbaccess.pbl into a new PBL that we'll call 'remoteobjects.pbl'. We also need to move the two datawindow objects to this PBL since they are used by the NVO.

 

Hosting remote objects

Hosting remote objects is really easy. Just include the PBL that contains them in the DPB Server application's library path. So we'll just add remoteobjects.pbl to the library list for pbserver. The next time you start this application the objects in remoteobjects.pbl will be available to the clients connecting to this server.

Next we'll look at how to change our monolith pbaccess application so that it now uses nvo_employee hosted on the DPB server.



Introduction

Strategy
Building the monolith
Building the DPB Server
Building the PB Client

Setting up the DPB Server
Deploying the PB Client

Points to Ponder
Where to go from here

 DownloadDownload the application

What's Next?

Previous  Next Home
1