Skip to content. | Skip to navigation

Sections
Personal tools
You are here: Home Accelerate Articles Best practices and performance considerations using RedBack Objects

Best Practices and Performance Considerations Using RedBack Objects

Learn the best practices of RedBack® Object planning, creation, and use for an effective Web site. Poorly planned use of RedBack Objects could mean a slow-performing Web site (and an unnecessary load on your database server), whereas the well-planned use of RedBack Objects can mean a fast, productive site.

Recommended tactics for Web Developers using U2 Web Development Environment to access UniData or UniVerse databases

Level: Intermediate

Ray Else ( relse@rs.com), Support Engineer, Rocket Software

19 Jan 2006


Introduction

U2 Web Development Environment (U2 Web DE)  is a middleware tool that allows you to easily access data in Rocket U2 UniData® or UniVerse® databases. U2 Web DE works with most middleware languages like Java, ASP.NET/C#, ASP.NET/VB, ASP/VBScript. U2 Web DE even works with Coldfusion and PHP through the supplied Java classes. RedBack Objects are also accessible from XML/SOAP requests.

Typically, you create RedBack Objects to manage the database access, objects with properties, and methods to allow the reading and writing of database data. You use the U2 Web Designer tool to define an object's properties and methods and optionally to write the method code in UniData or UniVerse Basic.

This article emphasizes that the planning of your RedBack Objects is almost as important as the creation of them. Poorly planned use of RedBack Objects could mean a slow performing Web Site (and an unnecessary load on your database server), whereas the well-planned use of RedBack Objects can mean a fast, productive site. This article covers best practices of RedBack Object planning, creation, and use for an effective Web site.

 

Best performance usages

Q: Which RedBack Object should I use for best performance?

With the U2 Web DE Designer tool one creates a RedBack Object by selecting to inherit a particular predefined RedBack Object "object/class", such as the RBO or uObject or uQuery or SLRBO "object/class". That way you start your new object with that object's properties and methods. Then you typically add your own properties or methods or set values into the properties to indicate what actions and database values are required.

If you are concerned primarily with performance and flexibility, then the stateless RedBack Object (SLRBO) is the best object to select to inherit from and build your own objects. This object is the fastest and puts the least load on both your network and your database server.

SLRBO - StateLess RedBack Object
The fastest RedBack Object, this very flexible, stateless object is good for single record reads (or multiple records delimited in some way) and writing away data to one or more files; requires you to write the methods/subroutines that do the reading or writing. Use this object whenever possible in your application because of its speed and light load on a system.
  • Note: An SLRBO object does not write to the WWSTATE database file, so no garbage collection of the object's work is required on the database server.

If your task requires that a recordset or dataset/datatable be returned, which the SLRBO does not do, then you can manually populate the recordset or dataset/datatable from a delimited string of properties in your SLRBO. For example, one of your properties could contain all the keys returned, delimited by commas, whereas another property returns all the names associated with those keys, also delimited by commas.

When returning records as delimited strings in an SLRBO, it is usually a good idea to have a property (called, for example, RecordCnt) that specifies how many records are returned this way, including "0" when no records are returned.

You should also always have a minimum of one property for status codes and/or messages from the backend database methods (Basic programs), called, for example, Status or ErrCode. This way you can programmatically handle backend problems, such as not being able to open a specific file at the Web middle layer.

You can optionally have a validation-related status code and/or message for the backend database methods to tell the Web program that mandatory input was not passed through the object's properties, or input that was passed was not in the proper range.

  • Note: If your task requires you to call an SB+ process, then you must use the slower, stateful sbObject. If you want to have a recordset returned and do not want to manually create one from an SLRBO object, then you can use either the uQuery object or the "non-object" RPC call. For more information on the sbObject, uQuery or "non-object" RPC calls, please refer to your official U2 Web DE documentation.
 

Creating RedBack Objects

Q: Should I create a RedBack Object for each file they are going to access, or one for each logical business object (like an Order which may be composed of data from several files)?

The answer, if you are concerned primarily with performance, is a big NO to the first, and a qualified Yes to the second. The fastest design is to build a RedBack Object (typically an SLRBO) for all the data you want to display on a page for a specific task, no matter how many files it comes from. You do not want to be doing multiple network/database hits per user interface page/screen, if you can avoid it. And luckily, the SLRBO is flexible enough to handle bringing complex data from multiple files back in a single database hit.

Let's take the example where you want to display an Order's details, including shipping info and full descriptions of codes used in the order record. You need to get info from five different files: Order, Customer, OrderLines, Products, and ShipCodes files. For best performance, you should design one RedBack SLRBO with one method (Basic subroutine program [that may call other subroutines]) that collects all the data you need to display.

Let's say an SLRBO called ORDER has the following data properties:

OrderKey (in - from user)
CustomerId (out - from ORDER file)
CustomerName (out - from CUSTOMER file)
ProductIds (out - from ORDLINES file)
ProductDescs (out - from PRODUCT file)
ProductQuantities (out - from ORDLINES file)
ShipCode (out - from ORDER file)
ShipCodeDesc (out - from SHIPCODES file)

In addition, you would add an error code and message property in case you cannot open the file or find the Order in the file with that OrderKey:

ErrCode (out)
ErrMsg (out)

Then you could have one method, called, for example, DoRead. This DoRead method would call a Basic subroutine program that you write, say WEBREADORDER, that would get the OrderKey value and use it to read the CustomerId and ShipCode from the ORDER file. It would then get the CustomerName from the CUSTOMER file. Then it would get the ProductIds and ProductQuantities from the ORDLINES file and get the ProductDescriptions from the PRODUCTS file. Finally, it would get the ShipCodeDesc from the SHIPCODES file.

  • Note: To simplify debugging of your Web-called Basic subroutine "methods", you can use two (or more) subroutines: One that is a kind of U2 Web DE wrapper to the other that does the business logic. That way you could easily write a non-U2 Web DE Basic program wrapper to call your business logic subroutine to test it completely outside of the Web environment. The following example shows all the logic in one program:
SUBROUTINE WEBREADORDER
* Web Read Order Wrapper routine
* Note this routine is written for UniData Basic, 
* but UniVerse Basic would be similar.
*
$INCLUDE WWINSERT RBO.H
STAT = RBO.getProperty("","OrderKey",ORDERKEY)
IF STAT # 0 THEN
   STAT = RBO.setProperty("","ErrCode","1")
   STAT = RBO.setProperty("","ErrMsg","OrderKey property problem")
   RETURN
END
IF ORDERKEY = "" THEN
   STAT = RBO.setProperty("","ErrCode","2")
   STAT = RBO.setProperty("","ErrMsg","OrderKey from web is blank")
   RETURN
END
* Got Key so we open file.
* Note we can use standard file open syntax
*  OPEN "MYFILE" TO F.MYFILE ...
* or take advantage of RedBacks open-files subroutine which opens
* files once (per RedBack responder), 
* keeping their handles in Named Common.
* For best performance we use the RedBack Open routine WW.FILEVAR.S
CALL WW.FILEVAR.S("ORDER", 1, F.ORDER, ERR1)
CALL WW.FILEVAR.S("CUSTOMER", 1, F.CUSTOMER, ERR2)
CALL WW.FILEVAR.S("ORDLINES", 1, F.ORDLINES, ERR3)
CALL WW.FILEVAR.S("PRODUCT", 1, F.PRODUCT, ERR4)
CALL WW.FILEVAR.S("SHIPCODES", 1, F.SHIPCODES, ERR5)
IF ERR1 + ERR2 + ERR3 + ERR4 + ERR5 # 0 THEN
   STAT = RBO.setProperty("","ErrCode","3")
   STAT = RBO.setProperty("","ErrMsg","Error Opening Files")
   RETURN
END
* note for fastest record manipulation we could use a MATREAD,
* but here we are only grabbing a couple data elements
READ R.ORDER FROM F.ORDER,ORDERKEY ELSE
   STAT = RBO.setProperty("","ErrCode","4")
   STAT = RBO.setProperty("","ErrMsg","Order not found:":ORDERKEY)
   RETURN
END
CUSTOMERID = R.ORDER<1>
SHIPCODE = R.ORDER<3>
* Get Ship Desc
READ R.SHIPCODES FROM F.SHIPCODES,SHIPCODE THEN
   SHIPCODEDESC = R.SHIPCODES<1>
END
* Get Customer Name
READV CUSTOMERNAME FROM F.CUSTOMER,CUSTOMERID,1 ELSE
   CUSTOMERNAME = "unknown"
END
* Get Line Items
SELSTMT = 'SELECT ORDLINES WITH ORDKEY ="':ORDKEY: '"'
* Note we capture output to keep from clogging
* the RedBack responder "out" log files
* with junk messages.
EXECUTE SELSTMT CAPTURING JUNK
IF SYSTEM(13) < 1 THEN
   STAT = RBO.setProperty("","ErrCode","4")
   STAT = RBO.setProperty("","ErrMsg","No line items on order")
   RETURN
END
EOF = 0
CNT = 0
DELIM = @VM
PRODUCTIDS = ""
PRODUCTDESCS = ""
QUANTITIES = ""
LOOP
   READNEXT ID ELSE EOF = 1
UNTIL EOF DO
   READ R.ORDLINES FROM F.ORDLINES,ID THEN
      CNT += 1
       * note we use valuemark and not fieldmark for input
       * into RedBack property
       PRODUCTIDS<1,CNT> = R.ORDLINES<1>
       QUANTITIES<1,CNT>  = R.ORDLINES<2>
      * Get Product Description
       READV PDESC FROM F.PRODUCTS,PRODUCTIDS<1,CNT>,1 ELSE
          PDESC = "unknown"
       END
       PRODUCTDESCS<1,CNT> = PDESC
   END
REPEAT
* Finished gathering data so set properties and return.
* Note we accummulate the returned status of the sets so
* we can check for error at end instead of each time.
* Note property names are case sensitive.
STAT = ""
STAT<1,-1> = RBO.setProperty("","CustomerId",CUSTOMERID)
STAT<1,-1> = RBO.setProperty("","CustomerName",CUSTOMERNAME)
STAT<1,-1> = RBO.setProperty("","ProductIds",PRODUCTIDS)
STAT<1,-1> = RBO.setProperty("","ProductDescs",PRODUCTDESCS)
STAT<1,-1> = RBO.setProperty("","ProductQuantities",QUANTITIES)
STAT<1,-1> = RBO.setProperty("","ShipCode",SHIPCODE)
STAT<1,-1> = RBO.setProperty("","ShipCodeDesc",SHIPCODEDESC)
* check if error setting any properties (due to misspelling/case)
IF SUM(STAT<1>) # 0 THEN
   STATMESS = "Error setting Properties, STAT = ":STAT
   STAT = RBO.setProperty("","ErrCode","5")
   STAT = RBO.setProperty("","ErrMsg",STATMESS)
END
RETURN



The following is a code snippet of an ASP.NET/VB page that uses the object and calls the above method:

  • Note: Using Java or XML, you do not have to call the "create" of an SLRBO, so you save one network hit as compared to stateful objects. Microsoft technology supplies Open3 in RedBack 4.2.6 and above. This does not do the extra network hit that an Open2 does, so you should change your code to use Open3 (for SLRBOs only!) as soon as you upgrade.

 

Listing 2. ASP.NET/VB code snippet showing object call

 

' Note - Open3 in RB 4.2.6 is faster; here we use older Open2
  ro.Open2("mydb", "MYMOD:ORDER", "", "", "")
  'Set Order Id into Object Property called OrderKey
  prop = ro.Property("OrderKey")
  prop.Value = Id
  'Call Method to Read
  ro.CallMethod("DoRead")
  'Get Values from Properties and put in Text of Labels
  prop = ro.Property("CustomerId")
  CustomerId.Text = prop.Value
  prop = ro.Property("CustomerName")
  CustomerName.Text = prop.Value
  prop = ro.Property("ProductIds")
  ProductIds.Text = prop.Value
  prop = ro.Property("ProductDescs")
  ProductDescs.Text = prop.Value
  prop = ro.Property("ProductQuantities")
  ProductQuantities.Text = prop.Value
  prop = ro.Property("ShipCode")
  ShipCode.Text = prop.Value
  prop = ro.Property("ShipCodeDesc")
  ShipCodeDesc.Text = prop.Value
  prop = ro.Property("ErrCode")
  ErrCode.Text = prop.Value
  prop = ro.Property("ErrMsg")
  ErrMsg.Text = prop.Value

 

 

Further improve performance

Q: What else can I do to improve performance, besides making smart use of RedBack Objects?

Keep in mind a couple of key issues with U2 Web DE:

Number one:

A U2 Web DE responder (at version 4 and below) will take a request and not be able to service any other requests until it is finished. These other requests will have to be handled by other responders (if there are any others that are not busy themselves or restricted from running, based on your Webshare licensing), or they will wait in the port for the responder to finish. To ensure a fast turnaround of request/response:

  1. Use SLRBOs for speed, and write them in such a way that the subroutines themselves are subsecond response. (That means you might have to add a secondary index on a file you are querying, for example, or, where it makes sense, even pre-process data at night into data marts of a sort.)
  2. Buy enough WebShares and turn on enough U2 Web DE responders in an account so you have little or no queuing of incoming requests. (See the U2 Web DE doc on perfrgw, a little utility that shows you the performance of U2 Web DE responders on your database server and whether you are experiencing license wait time.)
  3. Where you are launching long, printed (or emailed) reports (in an intranet type application, for example), consider having the Basic subroutine phantom do the work so the responder isn't tied up waiting for the report to complete.

 

Number two:

U2 Web DE can be configured to run in development mode or production mode on any particular account. The difference can be one or more seconds per request! This is controlled by a parameter called "startbackend" in the U2 Web DE scheduler config file (rgwresp.ini on the database server). If you set this to "2," you are in development mode, which means you do not have to restart U2 Web DE for the responders to pick up changes to your Basic subroutines -- the responder logs itself in to take the request, which is slow. If you set this to "1," when you start U2 Web DE, all your responders log in and take requests without relogging in -- typically much faster. But this means if you change Basic subroutines, you need to restart U2 Web DE for the responders to pick up the change.

In Listing 3, from rgwresp.ini, the newdb database is set to run in production mode, with four responders turned on:

 

Listing 3. newdb database set to run in production mode, with four responders turned on

 

[newdb]
   workdir=C:\u2databases\newdb
   port=8409
   startbackend=1
   nresponders=4

 

Back to top

 


Summary

In this article, we have covered how you should plan your use of U2 Web Development Environment (U2 Web DE) RedBack Objects to ensure good performance of your Web application.

If you have any general questions, please feel free to contact u2askus@rs.com, or you can contact me directly at relse@rs.com.

Resources

Learn

 

About the author

Ray Else photo

Ray Else works for Rocket U2, with seven years experience helping clients develop Web/U2 Applications using RedBack Objects. He has an M.S. in technical instruction/technical writing/film history from the University of North Texas. His undergraduate degree is in computer science from Texas A&M; - Commerce.

Document Actions