PowerBuilder Tips, Tricks, and Techniques

Berndt Hamboeck

Subscribe to Berndt Hamboeck: eMailAlertsEmail Alerts
Get Berndt Hamboeck: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

PowerBuilder: Article

'NetStart' your PowerBuilder Application

'NetStart' your PowerBuilder Application

One of the biggest problems in an enterprise is deploying the application. Usually you have to deliver a new release of your application to several hundred workstations. This may be a time-consuming and very cost-intensive task.

Think of rolling out the newest and coolest version of the order application of your enterprise: this superior version has so many new functionalities that your users will love it.

When we think about rolling out a new version, we must keep a few things in mind:

  • The cool new version has to be packed for distribution.
  • Database conversion scripts have to be given to one or more DBA.
  • Distribution has to take place.
  • The development team should be available during roll out.
Let's have a closer look at these points.

Database Conversion
We'll have a few new tables that have to be deployed into the production system. And we may also have some stored procedures, triggers, views, user-defined data types, and last, but not least, some predefined rows (data) in the new tables. We may also have to convert existing data in a table into, let's say, two different tables because our business logic has changed.

What Happens If Something Fails?
What would fail at this early stage of deployment? We installed all the scripts (adding new tables, filling them with data, converting our tables) on a test machine and everything was fine. We delivered everything to our DBA for the production environment and it all looked fine; however, sometimes (as you already know) bad things happen. We had sent the wrong user-defined data type to the DBA and now our text column was too short. Fortunately, we noticed it and sent the right script to the DBA; he made a bad joke and everything was fine. The database was up and running and our users were happy with the new version.

Packing for Distribution
I think you'll agree when we say that deploying to a Windows environment (yes, I know we're in an enterprise, but let's face the truth: most of them use Windows as clients) on a large scale is much easier when you use automated installation. However, there are still many tasks involved when you apply automated procedures to multiple servers and client computers throughout your organization. These tasks include:

  • Distributing the application files to all sites, including remote sites and sites without technical support staff
  • Monitoring the distribution to all sites
  • Securely providing enough operating system rights to do the upgrade
  • Automatically initiating the installation of the software package with the possibility of allowing the user to control the timing
  • Resolving problems related to the distribution or installation
  • Reporting on the rate and success of deployment

    It's not just "zip it up and put it on a floppy." In an enterprise, there are a lot of people involved, so it takes time and costs money.

    What Happens If Something Fails
    If you're a developer, you've no doubt been involved in this type of situation:

    Everything is going well; the application is tested and ready to deploy, but now it comes: the phone is ringing and someone wants a "little" change in the application; just another query argument in one of the generated reports (or DataWindow exports) you implemented a few weeks ago. It doesn't help if you complain that you're deploying tomorrow.

    You agree to implement the "last minute" enhancement request and change something on the report, just a small enhancement. You open the window, add the new stuff, click run, and see that it looks fine; you're done testing. Yes, I know, there are test plans, test documents, code reviews, and a lot of useful things besides hacking around in PowerBuilder and implementing the nitty-gritty details, but I'm sure you've been in this situation. It may have worked, and everything was fine when the stuff went out the next day, but not this time!

    The application is distributed to more than 400 users; a unique situation comes up and your PowerBuilder application crashes. You already know where it crashed. Yes, it's the part with the "last minute" change. Just a small enhancement, could be done easily in minutes, blah, blah, blah. You remember these words when your project manager is standing in front of you, wanting some answers. You already know that your users don't like the application - there might be several reasons for it (sometimes politics are more involved than they should be) - and you know how much it costs and how long it takes to deploy again. You don't need to have your project manager standing in your doorway staring at you.

    What can you do? Well, we have the best development tool under the sun: PowerBuilder. It can help save our jobs and save some money for the company as well.

    NetStart PowerBuilder Applications
    You may have read about Java Web Start - a technology that simplifies the deployment of Java applications. It enables you to launch full-featured applications from your Web browser with a single click. Hmm, that sounds great and is almost exactly what we need. Maybe we can adopt this for our requirements.

    It would be great if our application could maintain itself without distributing anything. As you may know, PowerBuilder generates executables in two formats: machine (aka c-code) and interpreted (aka p-code). The project painter includes options for machine-code generation and "incremental and full rebuild" functionality to ensure the integrity of the objects before generating the executable. I usually build PBDs, because the generation is a lot faster, and the precompiled code and the visual design is already in the PBL; it's copied over to the PBD (without copying the source code) and PowerBuilder is not going to create c-code and compile it into a machine-code executable.

    When you create PBDs, the objects in the PBD are compiled into it, not into the executable. Have you ever tried to start your executable and delete one or more of the PBDs after you've started the application? Yeah, you're able to delete them (but you can't continue to use your application because it will fail when it wants to load an object from a PBD that doesn't exist anymore).

    We can delete the PBDs at runtime and copy new ones, for example, from the network. Hmm, good idea, but not all users can connect to a special hardware drive (I've seen enterprises that had a "crippled" WinWord, so they were only able to do some very special things within it). What now? Yes, our application uses a database, so we'll store the PBDs in the database. Oh, did I hear some "Huh, the database will have to do a lot when 400 users want the complete new application at 8:00 a.m." Okay, I agree, but:

  • Who said we need the whole application? Often we'll change just one or two PBDs.
  • We'll zip the PBDs when we load them into the database and unzip them in memory on the users' machines.

    No more buzzing? Okay, let's recapitulate what we need:

  • A new database table
  • A script for the DBAs, so they can deploy the PBDs into production databases
  • A small application where we can deploy PBDs into a test database and create files for the DBAs; they'll bulk copy these files into the production database
  • Enhance our enterprise application to check if there's a new version in the database

    The Implementation
    We'll go through the implementation step by step, but you can download the full source code from www.sys-con.com/pbdj/sourcec.cfm or from www.bhitcon.net. (I'll try to get it on the CD of the upcoming PowerBuilder 9 books [www.pb9books.com].)

    The Database Design
    Store the PBDs in the database and create a new table called com_blb (see Listing 1). It should be possible to store PBDs with the same name for different projects. The PBD will be stored in an image column. A flag is needed to tell us if the stored data is zipped. The application will identify if it needs to get a new PBD on the basis of the comparison between the stored date and the creation date of the local (already deployed) file. Last, but not least, we'll store a comment, maybe a short description of what changed.

    You can see a suggestion of the database table in Figure 1.

    The 'Packager'
    We've built a small client application (see Figure 2) that should accomplish the following tasks for the user:

  • Choose a PBD
  • Save the chosen PBD in the database
  • Create a file that could be used with bulk copy to store the PBD in the database
  • See which PBDs are stored in the database and restore it into a directory

    Read the PBD
    The button "read file from disk" opens a PBD, reads it in 32K chunks, and stores it in an instance variable of type BLOB. We'll also zip this BLOB to make it smaller (Figure 2 shows that with a very small PBD you already save about 80% of the space and, as a result, a lot of network traffic when the PBD is retrieved later on).

    Listing 2 provides the complete source code for the button. The only problem here is that we need to know how to zip a BLOB.

    Compress the PBDs Using zlib
    zlib is a library of C routines that can be used to compress or expand files using the same deflate algorithm popularized by PKZIP 2.0. zlib is efficient, portable, and free. You can download it from www.gzip.org/zlib/.

    The origins of zlib can be found in the history of Info-ZIP. Info-ZIP is a loosely organized group of programmers who give the following reason for their existence:

    "Info-ZIP's purpose is to provide free, portable, high-quality versions of the Zip and UnZip compressor-archiver utilities that are compatible with the DOS-based PKZIP by PKWARE, Inc."

    These free versions of Zip and UnZip are world-class programs and in wide use on platforms ranging from the orphaned Amiga through MS-DOS PCs up to high-powered RISC workstations. But these programs are designed to be used as command-line utilities, not as library routines. People have found that porting the Info-ZIP source into an application could be a grueling exercise.

    Fortunately for all of us, two of the Info-ZIP gurus took it upon themselves to solve this problem. Mark Adler and Jean-loup Gailly single-handedly created zlib, a set of library routines that provides a safe, free, and unpatented implementation of the deflate compression algorithm.

    One reason for zlib's creation was to use it as the compressor for PNG format graphics. After Unisys belatedly began asserting their patent rights to LZW compression, programmers worldwide were thrown into a panic over the prospect of paying royalties on their GIF decoding programs. The PNG standard was created to provide an unencumbered format for graphics interchange. The zlib version of the deflate algorithm was embraced by PNG developers, not only because it was free, but it also compressed better than the original LZW compressor used in GIF files.

    zlib is good for more than graphics developers, however. The deflate algorithm makes an excellent, general-purpose compressor and as such can be incorporated into all sorts of software. We use it to compress our PBD files. To do this we need to declare two external functions:

    Function Long compress
    (Ref Blob compr, Ref Long comprLen, Ref Blob buf, Long buflen)
    Library "ZLIB.DLL"
    Function Long uncompress
    (Ref Blob uncompr, Ref Long uncomprLen, Ref Blob compr, Long lcomp)
    Library "ZLIB.DLL"

    These two functions take a BLOB that will be compressed or uncompressed. I'd recommend creating an NVO (and save it as n_zlib), which we'll use in our client application and later in our enterprise application (see Listing 3). (Due to space constrants, Listings 3-9 can be downloaded from www.sys-con.com/pbdj/source.cfm.)

    Store the PBD in the Database
    This is simple and doesn't need to be commented. Just create a new entry in the database, then update the same row to bring the BLOB holding our packed PBD (if the user has checked the "use zlib" option) into the image column. Listing 4 provides the complete source code.

    Create a BCP File
    To move data to and from our Adaptive Server database, use the BCP (bulk copy) utility from the operating system as a standalone program. Adaptive Server can accept data in any character or binary format, as long as the data file describes either the length of the fields or the terminators, the characters that separate columns. Since we don't know the length of the zipped PBD and we don't want to change our script for the DBA every time we choose the second option, we take termination characters. As shown in Figure 2, I've defined the termination characters as |TTTTT|. You can choose anything you want, but be careful that it's a string that won't be in a PBD or your import won't work. Listing 5 provides the full source code.

    The next step is to write a script that uses BCP to publish the database.

    First, we need to provide it with basic data information and prepare both the data for transfer and the command to access the data. We must supply the following information to transfer data successfully to Adaptive Server:

  • Name of the database and table
  • Name of the operating system file
  • Direction of the transfer
  • A format file that holds the column description and terminator for each column

    You can see the format file and the call for BCP in Listing 6.

    Remember, when we import data from a file using the BCP utility, it inserts data into an existing database table, so don't forget to delete any existing rows when publishing newer PBD files or you'll add blb_savedate to the primary key. This makes it possible to enhance the enterprise application to take only a special version (think of a future version where the start_date is in the future, and the [most] current version where the blb_savedate is smaller than today's date).

    The Version Check
    What does the version check need to do?

  • Connect to the database and see if there are some PBDs stored for our project.
  • If we find one or more entries, compare the blb_savedate with the distributed PBD's "last modified date."
  • When the application files are older, we have to grab them from the database, unpack them, and overwrite the local ones.

    There's more than one way to implement it. Either we add a library where we store user objects that do the version check for us, or write a small executable where we pass all the information that's needed to do the version check. The second solution might enable us to replace the .exe file of our enterprise application, which is not possible with the first solution as it's locked all the time. Anyway, I'll point you in the right direction by implementing solution one (you can implement solution two as homework).

    Let's start by enhancing our enterprise application with the code in Listing 7. The first line you see checks if the application is running as an executable (we don't want to download a new version when we're in the development environment); next do the version check. If there's a new version available, close the application by calling HALT CLOSE. When PowerBuilder encounters Halt with the keyword CLOSE, it immediately executes the script for the close event for the application and then terminates the application. If there's no script for the close event at the application level, PowerBuilder immediately terminates the application. In the close event of the application object, check the variable ib_restart. If it's true, use the PowerBuilder function Restart to restart the application.

    The next step is to write the function of_check (see Listing 8). Grab the complete library list for the application and convert it into an array of strings to make it easier to loop through all the entries. The next step is to get the current directory; we need this information to save the new version into the correct directory. Now retrieve the information from the database into a DataStore (note that we're not able to retrieve our image column). If the date check says there's a PBD to restore we call the function of_ restorefile.

    Note: You can find all the Win32 API calls in the PFC. If you don't want to grab it from there, download the complete source code from PBDJ's Web site.

    The function of_restorefile gets the BLOB from the database and unpacks it in memory using the zlib (see Listing 9). A nice feature is that it keeps the old files and remembers which ones are replaced. If something fails, we can undo our work. The only problem here is that we have to save the BLOB in 32K chunks.

    The function of_undo simply moves the old files back and restores the application.

    Long ll_file, ll_files

    for ll_file= 1 to ll_files
    IF FileMove(is_replaced[ll_file] + "_old", is_replaced[ll_file])
    <> 1 THEN
    return -1
    END IF

    return 1

    PowerBuilder can provide the same features as Web Start. Many techniques that are offered in Java have been available in PowerBuilder for a long time. This great tool can save your enterprise a lot of money, not only during development, but also during deployment. Let your project manager know what a great tool PowerBuilder is and see if you can get some extra money. ;-)

  • More Stories By Berndt Hamboeck

    Berndt Hamboeck is a senior consultant for BHITCON (www.bhitcon.net). He's a CSI, SCAPC8, EASAC, SCJP2, and started his Sybase development using PB5. You can reach him under [email protected]

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.