Title: Migration
1Reach Your Technical Peak 2004
2Writing Modern ProgressTechniques for using
the 4GL in OpenEdge
3Agenda
- Introduce a sample application
- Walk through the code for the application
- Review the programming constructs and their value
- Notes on Extending your application!
4Example application
Client
Server
Client super procedure Clientsuper.p
Client window procedure Modernwin.w
Server support procedure Ordersrv.p
Temp-Table
Client support procedure Orderproc.p
Application database
5Using Persistent Procedures
Client
Client window procedure Modernwin.w
Client support procedure Orderproc.p
6Persistent Procedures
- Avoid the traditional procedure hierarchy
- Let your application be more event-driven
- Treat a procedure as an object with a handle
- Code internal procedures and functions in the
main procedure - Share one running instance of the procedure
DEFINE VARIABLE hOrderProc AS HANDLE NO-UNDO.
RUN orderproc.p PERSISTENT SET hOrderProc.
7Using Handles
- Every object instance has a handle
- Procedures
- Buffers, Queries, Temp-Tables
- Fields, Browses
- Use the handle as a pointer to the object
instance - Extending your application Pass object handles
to new procedures that manipulate the object in
some new way.
8Using Super Procedures
Client
Client super procedure Clientsuper.p
Client window procedure Modernwin.w
Client support procedure Orderproc.p
9Super Procedures
- A super procedure is a persistent procedure
- The ADD-SUPER-PROCEDURE method uses its contents
to extend another procedure - You can have multiple levels of behavior
- Multiple internal procedures with the same name
- RUN SUPER transfers control from one to another
- Share a single instance within a session
- Define generic logic used by many procedures
- Extending your application with super procs
10How Orderproc.p starts Clientsuper.p
/ Is it already running? / hClientSuper
SESSIONFIRST-PROCEDURE. DO WHILE
VALID-HANDLE(hClientSuper) AND
hClientSuperNAME NE "clientsuper.p"
hClientSuper hClientSuperNEXT-SIBLING. END. /
If not, then run it. / IF NOT VALID-HANDLE(hClien
tSuper) THEN RUN clientsuper.p PERSISTENT SET
hClientSuper. / Make it a super proc in either
case. / THIS-PROCEDUREADD-SUPER-PROCEDURE(hClien
tSuper).
11Using Methods and Attributes
- You access Methods and Attributes through the
object handle - Each type of object has its own methods
- These perform operations on the object
- THIS-PROCEDUREADD-SUPER-PROCEDURE(hClientSuper).
- Each type of object has attributes
- These set or get information about it
- hClientSuperNEXT-SIBLING.
12Using Events
Client
Client super procedure Clientsuper.p
Client window procedure Modernwin.w
Client support procedure Orderproc.p
13Using Events
- The User Interface can use events to respond to
user input - ProDataSets also have events that can support
data management - Use events to make your application more flexible
in its use
14Event-driven code gets the Orders
- LEAVE trigger on the SalesRep field in the window
uses the Order support procedure
ON LEAVE OF cSalesRep RUN fetchOrders IN
hOrderProc (INPUT SELFSCREEN-VALUE).
- fetchOrders runs server-side code to pass back a
temp-table with the requested Orders
RUN ordersrv.p ON hAppServ (INPUT
pcSalesRep, OUTPUT TABLE ttOrder).
15Using Server-Side Logic
Client
Server
Client window procedure Modernwin.w
Server support procedure Ordersrv.p
Temp-Table
Client support procedure Orderproc.p
Application database
16Separate client and server logic
- Write separate procedures to run on the client
and server side of the application - Server-side procedures run in a Progress
AppServer session - Server-side procedures only should access the
database directly - Use temp-tables or ProDataSets to pass data to
the client
17Server-side procedure loads the temp-table from
the database
- Server-side procedure Ordersrv.p loads the
temp-table from the database and returns it to
the client
/ Procedure ordersrv.p does server-side order
handling. / DEFINE TEMP-TABLE ttOrder LIKE
Order. DEFINE INPUT PARAMETER pcSalesRep AS
CHARACTER NO-UNDO. DEFINE OUTPUT PARAMETER TABLE
FOR ttOrder. FOR EACH order WHERE
Order.SalesRep pcSalesRep CREATE
ttOrder. BUFFER-COPY Order TO ttOrder.
END.
- A ProDataSet could FILL the temp-table from the
database in a single method call
18Using User-Defined Functions
Client
Client super procedure Clientsuper.p
Client window procedure Modernwin.w
Client support procedure Orderproc.p
19Using User-Defined Functions
- Functions have a typed RETURN value
- Functions can be used inside expressions
- Dont overuse them - there are restrictions
- No I/O blocking inside a function
- No record indexing inside a function
- Function prototype lets you define its signature
and return type before use - Use DYNAMIC-FUNCTION to determine this at runtime
20Function example
- Function prototype defines it before use
FUNCTION getFieldGroup RETURNS HANDLE IN
SOURCE-PROCEDURE.
- You can use the function in place of the value it
returns
RUN attachBrowse (INPUT getFieldGroup(), INPUT
hTableBuf).
- The function itself returns a typed value
FUNCTION getFieldGroup RETURNS HANDLE DEFINE
VARIABLE hObject AS HANDLE NO-UNDO. ASSIGN
hObject ModernWinHANDLE hObject
hObjectFIRST-CHILD / The frame /
hObject hObjectFIRST-CHILD. / Field group /
RETURN hObject. END FUNCTION.
21Searching a Super Procedure
Client
Client super procedure Clientsuper.p
Client window procedure Modernwin.w
RUN attachBrowse
Client support procedure Orderproc.p
22Searching a super procedure
- The Order procedure runs attachBrowse
- This is implemented only in its super procedure
- Progress locates the entry point there and runs
it as if it were part of the base procedure
23Walking the widget tree
- Many objects are compound objects
- They have a hierarchy of objects under them
- Window-gtFrame-gtFieldGroup-gtWidget
- Buffer-gtBufferField
- Browse-gtColumn
- Start at the top with FIRST-CHILD (or
FIRST-COLUMN for a browse) - Use NEXT-SIBLING to navigate
- Extending your application Walk the widget tree
of a frame or buffer handle passed to a new
procedure to extend it.
24Widget tree of a window
- The Window contains one or more frames
- Each frame can have one or more Field Groups
- The Field Group is like the DOWN in character mode
ASSIGN hObject ModernWinHANDLE hObject
hObjectFIRST-CHILD / The frame /
hObject hObjectFIRST-CHILD. / Field group /
- FIRST-CHILD of the group is the first widget
- Use NEXT-SIBLING to find all widgets
hObject phFieldGroupFIRST-CHILD. DO WHILE
VALID-HANDLE(hObject) AND hObjectTYPE
NE "BROWSE" hObject hObjectNEXT-SIBLING.
END.
25Using Dynamic Objects
Client
Client super procedure Clientsuper.p
Client window procedure Modernwin.w
CREATE QUERY
Client support procedure Orderproc.p
26Using dynamic objects
- Dynamic objects let you control what is created
at runtime - A single procedure can create an object to match
many requests - A single procedure can be a factory for many
objects of a given type - You must remember to clean up after yourself to
prevent memory leaks
27Creating a dynamic query
- Create the query object and get a handle
- Add the temp-table buffer to it
- Prepare it with the selection criteria
- Open it
- Position it to the first row in the results
CREATE QUERY hQuery. hQueryADD-BUFFER(phT
ableBuf). hQueryQUERY-PREPARE("FOR EACH "
phTableBufNAME). hQueryQUERY-OPEN().
hQueryGET-FIRST().
- Extending your application Replace generated
where clauses with dynamically prepared queries
28Running a procedure with an override
- The procedure connects the query to the browse
- It runs a procedure to display values in the
windows fields, passing in the browse handle.
hObjectQUERY hQuery. RUN displayFields
IN TARGET-PROCEDURE(INPUT hObject).
- TARGET-PROCEDURE tells it to go back to the base
procedure at the bottom of the super procedure
stack.
29Using Multiple Versions of a Procedure
Client
RUN displayFields
RUN SUPER
30Local behavior for displayFields
- The Order procedure has special code to run when
field values are displayed - It first locates the CreditCard field
DEFINE INPUT PARAMETER phBrowse AS HANDLE
NO-UNDO. DEFINE VARIABLE hField AS HANDLE
NO-UNDO. hField phBrowsePARENTFIRST-CHILD. DO
WHILE hFieldNAME NE "CreditCard" hField
hFieldNEXT-SIBLING. END.
31Chasing down a string of handles
- A succession of handles makes its own widget
tree - The string value of the credit card field of the
first buffer of the query of the browse
CASE phBrowseQUERYGET-BUFFER-HANDLE(1)
BUFFER-FIELD("CreditCard")STRING-VALUE WHEN
"Visa" THEN hFieldBGCOLOR 13. WHEN
"Master Card" THEN hFieldBGCOLOR 12.
WHEN "American Express" THEN hFieldBGCOLOR
11. OTHERWISE hFieldBGCOLOR 10. END CASE.
32Invoking the standard behavior
- RUN SUPER goes up the stack of any number of
internal procedures of the same name
RUN SUPER (phBrowse).
- The generic code in clientsuper displays each
field from the buffer in the window
hBuffer phBrowseQUERYGET-BUFFER-HANDLE(1). hFi
eld phBrowsePARENTFIRST-CHILD. DO WHILE
VALID-HANDLE(hField) IF CAN-DO("FILL-IN,COMBO
-BOX", hFieldTYPE) THEN
hFieldSCREEN-VALUE
hBufferBUFFER-FIELD(hFieldNAME)STRING-VALUE.
hField hFieldNEXT-SIBLING. END.
33Publishing an Event
Client
PUBLISH fetchNext
SUBSCRIBE TO fetchNext
34Publishing an Event
- When you press the Next button its CHOOSE event
publishes the event named fetchNext.
ON CHOOSE OF bNext PUBLISH fetchNext.
- The Order procedure subscribed to this event on
startup, so it is captured there.
SUBSCRIBE TO "fetchNext" ANYWHERE.
- So Progress runs the fetchNext internal procedure.
hBrowseQUERYGET-NEXT(). hBrowseSELECT-NEXT-ROW(
). RUN displayFields IN TARGET-PROCEDURE (INPUT
hBrowse).
35Using PUBLISH and SUBSCRIBE
- Use the PUBLISH statement to decouple an event
from its handler procedure - The PUBLISHer doesnt need to know the handle of
the procedure that deals with the event - This allows multiple subscribers, or none,
without error - SUBSCRIBE to an event in a specific procedure
handle, or ANYWHERE - Extending your application with published events.
36Dont forget to clean up!
- You have to delete every dynamic object you
create when youre done with it - Procedures, queries, fields, temp-tables
- A widget pool can group objects for deletion
ON CLOSE OF THIS-PROCEDURE DO hQuery
BROWSE OrderBrowseQUERY. DELETE OBJECT
hQuery. DELETE PROCEDURE hOrderProc. RUN
disable_UI. END.
37Modern Progress Principles
Persistent Procedures for Reusable
Objects Handles to Access Methods and
Attributes Super Procedures for Standard Sharable
Behavior Events to Let the User Drive the
Application Server-Side Logic to Access the
Database Functions to Return Values to
Expressions Queries to Separate Data Access from
Blocks Dynamic Objects to Define Objects at
Runtime PUBLISH To Decouple Events from Handlers
38(No Transcript)