Showing posts with label trigger. Show all posts
Showing posts with label trigger. Show all posts

Saturday, 7 June 2014

Sendmessage versus postmessage

If you wanted to send a message from one form to another, you could simply use sendmessage.  This was deprecated in favour of using activate, a command which has become pretty much a catch-all for all sorts of earlier commands, including run, perform, and spawn.  These all still work in Uniface 9.6, but as they were deprecated in Uniface 9.1, it's well worth trying to write these out of your code.

One example of this might be if you have retrieved multiple records in one form, and also have a second form open with related records in it; when you scroll through the occurrences in the first form you might want to post the primary key details through to the second form, so that only the records related to the current occurrence in the first form are displayed.

In order to do this, the first form would need to have code in the "Occurrence Gets Focus" <OGF> trigger, something like this...


  sendmessage "SECOND_FORM","PKEY","FIELD1.ENT=%%FIELD1.ENT%%%"

As you can see, because sendmessage is now deprecated, it is not highlighted as a reserved word.  You also get a compile warning like this...

  warning: 1000 - Deprecated statement 'sendmessage' used

You then need to have some code to receive this message in your second form, which needs to be in the "Asynchronous Interrupt" <ASYS> trigger, something like this...


  the_result = $result ;will be "message"
  message_id = $msgid ;will be "PKEY"
  message_data = $msgdata ;will be "FIELD1.ENT=xxx"

When using sendmessage or postmessage, $result will always be set to "message".  The second value that you define will become the $msgid and then third value will become the $msgdata.  

Please note:  If the <ASYS> trigger in the called component is blank then the application <ASYS> trigger will be called, as defined in the start-up shell.

So what's the difference between sendmessage and postmessage?  Can you simply go through and replace every sendmessage with a postmessage, or should you be using activate instead?

Well the difference is that sendmessage is synchronous and postmessage is asynchronous, which means that potentially there's a delay before the message will be received and processed with a postmessage.  Using an activate would be synchronous but you'd need to rewrite your code, probably moving the code in the <ASYS> trigger into an operation and then calling that from the <OGF> trigger.

Is this potential delay likely to cause a problem though?  Well for starters, can we see it in practice?  The answer to this is "yes", by putting sending code like this somewhere in a form (I went with the <EXEC> trigger)...


  putmess "Before sendmessage"
  sendmessage "TEST_PERF","MESSAGE","SENDMESSAGE"
  putmess "After sendmessage"

  putmess "Before postmessage"
  postmessage "TEST_PERF","MESSAGE","POSTMESSAGE"
  putmess "After postmessage"

And then putting the receiving code in the <ASYS> trigger, like this...


  putmess "In ASYS: ID=%%$msgid%%%, DATA=%%$msgdata%%%"

We can then run the form and view the message buffer...

  Before sendmessage
  In ASYS: ID=MESSAGE, DATA=SENDMESSAGE
  After sendmessage
  Before postmessage
  After postmessage
  In ASYS: ID=MESSAGE, DATA=POSTMESSAGE

As you can see, the sendmessage happens between the "before" and "after" (synchronously), whereas the postmessage happens at the very end (asynchronously).  This means that you have to be very careful about changing any sendmessage statements into postmessage statements - the code order will change, and you need to be aware of this and check this will not cause a problem.

As far as my testing has gone, the messages are always received and processed in the order that they were posted, as you may expect from a message queue.  Having said that, I've not found anything in the manuals that states explicitly that this order is enforced, so writing code that relies on the messages being processed in a particular order might not be wise.


Summary: The deprecated sendmessage command was sychronous whereas the postmessage command is asychronous, so you must be careful if you replace one with the other.  However, this is likely to be more straight forward than replacing with the activate command, as the manual suggests.

Wednesday, 30 May 2012

Undocumented feature - error stack

This is something which has previously never been documented by Compuware.  In the Uniface 9.5 manuals it is used in a code example, but isn't explained at all.   We first found it in 2008, when we were on Uniface 9.2.  I've called it an "error stack", because that's the context we use it in, but really it's accessing the process stack, so you can determine where you are within the code at runtime.  And it's as simple as this...

stack = $proccontext("STACK")

I could just leave it there, but that seems a little mean, so I'll continue :)

At this point the "stack" variable is populated with a Uniface list.  Each item in this list contains another list, which contains the following items...

  • TYPE - The type of item on the stack ("TRG" for trigger, for example)
  • INSNAM - The instance name of the form running (or application shell)
  • TRIG - The trigger of the form running ("execute", for example)
  • ENTITY - The entity name of the item (if you're in an entity or field trigger)
  • FIELD - The field name of the item (if you're in a field trigger)
  • MODEL - The model name of the item (if you're in an entity or field trigger)
  • MODNAM - The name of the item (the entry or global procedure name, for example)
  • LNR - The line number within the item
  • LIN - The line of code itself

So you can loop through this list (forwards if you want it like a stack, or backwards if you want it to be more readable) to determine how you managed to end up where you currently are, down to the line number.  This is really useful for outputting when errors occur, especially in global procedures, as you can see what form was running at the time, right back to the application shell.

Thanks to Mark R for telling me about this one!

Summary: It is possible to determine exactly where you are within code at runtime, which is really useful for error messaging.