Hello,
Is it true that older Progress client versions (9.1C or older) have problems with MESSAGE statements in user-defined functions (Error 2780)?
That's the rumour that goes here (is a MESSAGE an 'input-blocking statement'?) and because some of our customers still use 9.1C we try to stay away from using MESSAGE's in user-defined functions (or procedures (with MESSAGE's in them) that are called from user-defined functions), we always try to replace them with procedures.
I have now come to a point where MESSAGE statements are crucial and used in functions, but I would really be certain that this works as expected on older clients before putting it in production...
Thanks for any answers
Lieven
Within a function, you cannot define any input-blocking statements, such as a WAIT-FOR statement or any statement that prompts the user for input.
If your MESSAGE statements do not use VIEW-AS ALERT-BOX, BUTTONS you should be okay.
See:
http://tinyurl.com/y5aro5
http://tinyurl.com/y4pjup
Message was edited by:
Salvador Vinals
So in that case the following can pose problems?
MESSAGE "File not found!"
VIEW-AS ALERT-BOX INFO BUTTONS OK.
/* or */
DEFINE VARIABLE pOk AS LOGICAL NO-UNDO.
MESSAGE "Continue"
VIEW-AS ALERT-BOX INFO BUTTONS YES-NO UPDATE pOk.
IF pOk THEN
/* ... */
ELSE
/* ... */
Or is it safe to use these, because I don't get any runtime errors?
These two MESSAGE statements require user input. Avoid them in UDFs.
The thing is, I'm trying to use John Sadd's implementation of Exception Handling in 4GL and he effectively uses the MESSAGE statement as stated above (in an internal procedure called from a UDF) to display the exceptions to the user. Does that mean I can't be 100% certain that this won't generate 2780 error's?
John's code
http://tinyurl.com/yalcyr
I'm not easily satisfied, sorry
Salvador ... may I recommend tinyurl.com? Those long URLs do funny things to the format of the thread!
May I recommend that you download the AutoEdge code and check out the exception handling mechanism there? It doesn't have all the nice features of my exception and condition handling classes ( http://www.oehive.org/ExceptionClass ), but it is probably closer to what you are already doing.
Thanks Salvador! Much better!
Thanks, I'll look into AutoEdge, I hope it is usable in a Progress 9 environment...
But my real question isn't answered yet: Can I use a MESSAGE "Hello" VIEW AS ALERT-BOX... statement in UDF's and be certain it won't generate 2780 errors with our clients (here it seems to work...)
edit: The AutoEdge exception handling IS John Sadd's work mentioned earlier! He uses a UDF DisplayException() that calls internal procedure DisplayExceptionProc that displays a message. When you assume that the message statement is a blocking statement, than that isn't allowed...
Message was edited by:
lieven
Hi Lieven,
MESSAGE is not an input-blocking statement (strange that Salvador didn't know, since in the old days we complained a lot about this constraint
Run this code and see for yourself, the function with MESSAGE runs fine:
DEFINE TEMP-TABLE ttSample NO-UNDO
FIELD iKey AS INTEGER.
FUNCTION CreateKey RETURNS INTEGER(INPUT lpInputBlocking AS LOGICAL):
IF lpInputBlocking THEN
PROCESS EVENTS.
ELSE
MESSAGE "Hi there" VIEW-AS ALERT-BOX.
RETURN 10.
END FUNCTION.
CREATE ttSample.
MESSAGE "Call CreateKey(FALSE)" VIEW-AS ALERT-BOX.
ASSIGN iKey = CreateKey(FALSE).
MESSAGE "Call CreateKey(TRUE)" VIEW-AS ALERT-BOX.
ASSIGN iKey = CreateKey(TRUE).
Great demonstration.
Is 'MESSAGE is not an input-blocking statement ' documented anywhere? I could find nothing, and didn't want to pursue msgboxa winapi mechanics.
I've often wondered the same as lieven, and I've never used it for Salvador's reasons, but also because my personal, arguably religious opinion is that using functions for UI, or as substitutes for procedures is 'aesthetically incorrect' (ie. likely to cause future issues).
Is 'MESSAGE is not an input-blocking statement '
documented anywhere? I could find nothing, and didn't
want to pursue msgboxa winapi mechanics.
I think it's defined somewhere. But if you think about it, it makes sense that a messagebox is an exception: this statement can never invoke another 4GL statement. It's blocking at the MESSAGE-statement, so the runtime doesn't have to worry about reentrant code...
Progress documents in several places the 7 statements that are illegal in user-defined functions, non-void methods, and property accessor implementations. Specifically, the FUNCTION statement contains a note identifying these illegal statements and the help text for error 5622 also provides this information. In fact the help text states that the MESSAGE statement is NOT a statement that blocks for user input and therefore is legal in user-defined functions.
Error 5622 states:
UPDATE, SET, PROMPT-FOR, CHOOSE, INSERT, WAIT-FOR, and READKEY statements are not permitted inside a user-defined function, or inside a non-void method or a property GET or SET body. (5622)
You have an I/O blocking statement inside a user-defined function, a non-void method, or the body of a property accessor. These types of routines cannot tolerate blocking for user input. You need to remove the statement, or turn the user-defined function into an internal procedure, or make the method VOID. Note that a MESSAGE with an ALERT-BOX is not I/O blocking.
Progress documents in several places the 7 statements
that are illegal in user-defined functions, non-void
methods, and property accessor implementations.
The documentation generally uses weasel words like 'Input blocking statements include...', which is why this question arises.
Specifically, the FUNCTION statement contains a note
identifying these illegal statements
Yes, it is rather more specific there, though no explicit exclusion of alert-boxes.
and the help
text for error 5622 also provides this information.
Nope.
In fact the help text states that the MESSAGE
statement is NOT a statement that blocks for user
input and therefore is legal in user-defined
functions.
Nope.
Error 5622 states:
You have an I/O blocking statement inside a
user-defined function, a non-void method, or the body
of a property accessor. These types of routines
cannot tolerate blocking for user input. You need to
remove the statement, or turn the user-defined
function into an internal procedure, or make the
method VOID. Note that a MESSAGE with an
ALERT-BOX is not I/O blocking.
You obviously have the deluxe help. Mine (9.1D07) states (similarly, but note the important omission):
You have an I/O blocking statement inside a user-defined function. User-defined functions cannot tolerate blocking for user input. You need to remove the statement from the user-defined function, or turn the user-defined function into an internal procedure.
c
(Ends there with isolated 'c')
Assuming no corruption in my install, I guess it's a documentation bug in pre OE editions. Thanks for the pointers.
But if you think
about it, it makes sense that a messagebox is an
exception: this statement can never invoke another
4GL statement. It's blocking at the
MESSAGE-statement, so the runtime doesn't have to
worry about reentrant code...
Thanks, will mull this over another time, but it's 2.30AM here at the moment, and this is a little beyond me right now...
Thank you all!
My Progress installation's (9.1D06) help also lacks the "Note that a MESSAGE with an ALERT-BOX is not I/O blocking." line like knuthandsome's, so I think this is a documentation shortcomming in older versions. Thank you Evan for the error 5622 information, thank you Theo for the sample code.
On a sidenote: does this also mean that "PROCESS EVENTS" should be included in the list of input blocking statements?
Lieven
On a sidenote: does this also mean that "PROCESS
EVENTS" should be included in the list of input
blocking statements?
NO.
(From Help for PROCESS EVENTS).
"Processes all outstanding events without blocking for user input."
YES.
(From verified Knowledgebase P7924), also Theo's example.
"Input blocking statements include PROMPT-FOR, SET, UPDATE, WAIT-FOR, READKEY and PROCESS EVENTS."
Hope that clarifies the issue.
Seriously, regardless of the Help text, Theo's code demonstrates that using PROCESS EVENTS in a function won't work.
Issue clarified thanks!
I stand corrected. Thanks all for correcting my mistake.
I just burned myself with this again! I was refactoring some include file to some new OO classes and used a non-void method instead of a void method. Sure enough, somewhere down deep in the bowels of the code something was using the process events statement and caused this error to appear. Luckily QA caught it and I was able to correct the code by making it a void method return with an output instead. Luckily the impact was small here and we caught it in time.
This I/O blocking restriction will be removed in version 11. Coming in 10.2B02, there will also be a way to remove the restrictions by using a startup parameter (-IOEverywhere 1).
Awesome! Good to know.
Just to complete this: I've heard from tech support that 10.2B02 is expected to be out around Progress Exchange Online 2010.