John W. Colby
jcolby at colbyconsulting.com
Thu Feb 13 11:28:09 CST 2003
Arthur, I believe you are really talking about a message store process where messages get placed into a storage mechanism, and can be retrieved later? What happens if machine a needs Roll type Z but no one has it available? The message goes out and is stored. Machine C then (finally) produces Roll type Z and goes looking for messages requesting that roll type. Finding a message in the queue, it answers the message saying that it has a roll available (now). All kinds of issues immediately spring to mind that negate the usefulness of this... can Machine A be down waiting for Roll type Z? Or will it ask for Roll Type Y and go back to work. Etc. Basically the process I modeled was more like a CB channel. A message broadcasts. If anyone cares, they accept the message. They may or not even respond, depending on the reason for the message. Maybe they just accept the message and perform some process. Maybe they perform some process and respond with a message indicating process status. Those details have nothing whatever to do with the channel that broadcasts the message. The CB radio doesn't care who broadcasts or who listens or what is done with a message. It simply broadcasts messages. Broadcasters talk to expected listeners. Listeners understand what to do with messages addressed to them. I have read specs for messaging systems of the type discussed in the first paragraph. Companies like Microsoft have written software to handle situations like that. The stuff I am talking about obviously only addresses communication between processes inside a single copy of an FE running on a desktop. John W. Colby Colby Consulting www.ColbyConsulting.com -----Original Message----- From: accessd-admin at databaseadvisors.com [mailto:accessd-admin at databaseadvisors.com]On Behalf Of Arthur Fuller Sent: Thursday, February 13, 2003 12:08 PM To: accessd at databaseadvisors.com Subject: RE: [AccessD] Message Classe - was Off the wall Events question... This thread reminds me of some stuff I wrote a few years back in PowerBuilder. What I needed, which I don't readily see accounted for in your model (but it might be, via the Subj property) is a decentralized queue. In my case, I had to model a factory of unknown configuration. That is, instance x might have 2 paper machines, 3 cutters, 10 sheeters and so on. No way of knowing before actually visiting the site. Simplifying a little, the issue is this. Sheeters ask cutters for rolls. A given cutter C1 currently has rolls R1, R2 and R3 available for dissection. C1 posts 3 messages, 1 per roll. These go into a queue. Sheeter 1 requires some rolls of dimensions x, y and z, and scans the queue for appropriate objects, requesting same if any are found (up to the number required). It doesn't matter to Sheeter 1 where the rolls come from. All S1 knows is that it wants N rolls of said dimensions and quality. S1 doesn't even know how many sources of said rolls exist. It simply posts a requirement. To simplify even more, machine x knows nothing of machine y. They communicate through the public queue, and there could be several instances of both x and y. The Broadcast method indiscrimately sends messages to every machine regardless of type. The narrowcast method presupposes knowledge of the target(s). The problem sketched above IMO requires a Middlecast method: a shared queue of messages, with each sender indicating the message content and itself, and each receiver indicating the message type of interest, and itself. It's analogous to Many-to-Many, but implemented in machines not tables (tables, too, of course, but that's the plumbing). This model might be further affected by a priority column in the Required messages. Certain jobs, taking place on machines M1, M2 and M3, might have a higher priority than jobs requiring the same kind of rolls, but running on M4 and M5. Is it too late to squeeze this functionality in? A. -----Original Message----- From: accessd-admin at databaseadvisors.com [mailto:accessd-admin at databaseadvisors.com] On Behalf Of John W. Colby Sent: February 13, 2003 10:31 AM To: accessd at databaseadvisors.com Subject: RE: [AccessD] Message Classe - was Off the wall Events question... Jim, And in fact my message class (not sure about the one in the demo but I think so) has two message methods, one simple and one with all four properties (To, From, Subj, Msg). In point of fact of course, just because the message is "TO" someone doesn't prevent others from seeing the message. In fact users have to specifically filter on the to in order to determine that the message is for them. I actually started with the simpler message method (just the message param) but decided it would be helpful to have another method that one could use to tell the listener who the message was for, who it was from etc. I did it in fact precisely for inter-form communication where the receiving form was going to return a value back to the calling form, but it is generally useful anyway. It takes a little more code in the listening event but gives flexibility. BTW, I notice that you type the message to a string. I intentionally left mine a var so that I could if I so desired pass pointers to objects. For example, Drew's calendar could get a message: To: frmCalendar From: frmClient Subj: Message: PointerToTextBox Because the message param is a variant, the calendar function can simply use the value of the text box passed in, manipulate it, then place the value directly back in text box since it knows what object needs the returned value. John W. Colby Colby Consulting www.ColbyConsulting.com -----Original Message----- From: accessd-admin at databaseadvisors.com [mailto:accessd-admin at databaseadvisors.com]On Behalf Of Jim DeMarco Sent: Thursday, February 13, 2003 8:44 AM To: accessd at databaseadvisors.com Subject: RE: [AccessD] Message Classe - was Off the wall Events question... Hi John, Thanks for sharing the details of your message class. I put together a Messenger class when I was first learning about Interfaces that I'll detail here FYI. Your class allows an ojbect to send a message "To" another ojbect. Mine works in a lister motif where an object that implements the interface sends a message and anyone listening for messages from that object can retrieve them and act on them. The interface class, IMessage, contains two empty methods - SendMessage(MessageText As String) and GetMessage(). The interface is implemented by any class that wants to send or receive messages. The Messenger class contains one public event MessageReceived(), one property, Sender, that returns the type of object sending the message, a SendMessage function that creates the message (Sender object and message text), and calls a private function ActivateListeners that raises the MessageReceived event so any object listening can determine if they want this message. To set up a class to use the Messenger declare a module level Messenger object and implement the interface: Private Messenger As Messenger 'need to use for its send function Implements IMessage In the class IMessage_SendMessage function call Messenger.SendMessage passing in the message text and a reference to the class (Me). IMessage_GetMessage interprets the message and acts on it. An Init function where we'll pass in a Messenger object to use to pass messages (this Messenger object uses WithEvents and is created on the calling form or module). To use the class declare a module or global level Messenger object WithEvents and any objects that will use the Messenger: Private WithEvents g_oMessenger As Messenger Private oC1 As Consumer1 Private oC2 As Consumer2 Initialize the consumers to point to the Messenger (you could have more than one Messenger variable handling different types of message). Set g_oMessenger = New Messenger 'initialize all objects that need to communicate to same messenger object 'this causes them all to react to the messenger's MessageReceived event 'in this case g_oMessenger Set oC1 = New Consumer1 oC1.Init g_oMessenger Set oC2 = New Consumer2 oC2.Init g_oMessenger Now we just need to listen for the MessageReceived event: Private Sub g_oMessenger_MessageReceived() 'notify any listeners that there is a message 'route the message to the appropriate listener If TypeName(g_oMessenger.Sender) = "Consumer1" Then 'any obj that needs 'consumer1 messages GetMessage oC2 ElseIf TypeName(g_oMessenger.Sender) = "Consumer2" Then GetMessage oC1 End If End Sub The GetMessage function is a wrapper for the interface class: Private Function GetMessage(obj As IMessage) obj.GetMessage End Function There is also a SendMessage function to wrap the interface function of the consumer classes as well. Anyway, just wanted to run an alternate method by the list. A planned mod to this class is to use XML as the message format. Thanks, Jim DeMarco Director of Product Development HealthSource/Hudson Health Plan -----Original Message----- From: John W. Colby [mailto:jcolby at colbyconsulting.com] Sent: Thursday, February 13, 2003 1:28 AM To: accessd at databaseadvisors.com Subject: RE: [AccessD] Off the wall Events question... Drew, Given your familiarity with VB why don't you create an ocx. OCXs can raise events. That could be placed on a form (or even in a class which forms a wrapper to the ocx), then a reference to the ocx itself (not the class that contains it) could be dimmed in any form that needed it and it's event sunk in the form (or class). Something of that nature anyway. I used an ocx for the comm object from visual basic. By placing it on a form I could sink it's events in that form. I never tried to make the comm object dim a public object but if you can do that then other forms can set a reference to the same object by getting it from the open form. Each form that gets a pointer to the object should be able to declare it's own instance of the object withevents thus could sink the calendar's events. I don't know how you are going to tell the object what form / control is requesting a date service so that is a bit muddy. In a2K (which has RaisEvents) I built a message class for exactly this kind of situation. The message class was dimensioned public in a module, thus any other class that wanted to use it could dim a variable of type dclsMsg (Deep class!). The msg class simply had methods that anyone could call with a mail type of From / To / Subject / Message parameters. Anyone could send a message simply by referencing the global message class and calling the method. The message class then raised an event passing along the 4 parameters. Anyone that wanted to receive messages from the message channel dims a dclsMsg withevents, points to the global msg class, then sinks the message event. Thus any message on the channel gets to everyone watching the channel. It is up to each watcher to watch the "to" param for it's name or something that it knows means the message is to it. I used a form that when opened, grabbed a pointer to the message class, then watched for it's name in the "To" param. It performed it's action, then returned a message to the caller found in the "from" parameter, putting it's name in it's message's From param. The caller was watching for a return message. Does that make sense? To: "frmCalendar" From: "FrmClient" Subject: "txtCreditAprvdDate" Msg: #StartDate# the calendar processes the date, and when the user finishes with the calendar, returns the message: To: "FrmClient" From: "FrmCalendar" Subject: "txtCreditAprvdDate" Msg: #ManipulatedDate# The calendar form has dimmed withevents lclsMsg as dclsMsg and set it = gdclsMsg. It then sinks the message event from the message class. sub ldclsMsg_Msg(strTo as string, strFrom as string, strSubject as string, varMsg as variant) 'Do something with the message when it arrives if strTo = me.name then 'Do something cool with the message 'Save the strFrom to know what form sent the message 'Save the strSubject to know what control on the calling form the date is going back into. 'manipulate the date 'When the user is finished manipulating the date... ldclsMsg.Msg strFrom, me.name, strSubject, #ManipulatedDate endif end sub With a message channel like this, anyone can send a message, whether or not they are watching for a return message. Anyone can watch for messages simply by dimming a variable: dim ldclsMsg as dclsMsg set ldclsMsg = gdclsMsg 'this was initialized by the framework Once dimmed, the class (or form) watching the message channel sinks the message event sub ldclsMsg_Msg(strTo as string, strFrom as string, strSubject as string, varMsg as variant) 'Do something with the message when it arrives if strTo = me.name and strFrom = "frmCalendar" then 'Do something cool with the message if strsubject = "txtCreditAprvdDate" then txtCreditAprvdDate.value = varMsg endif endif end sub Notice that you can have as many of these message channels as you want. Set up a global message channel just for the calendar. Only forms wanting to use the calendar watch the channel. So... obviously this can only be done using a message class in A2K or above since only A2K or above can do the RaiseEvent in the message class. However in A97 you might be able to build something similar by using an ocx that is referenced in a variable in a class somewhere. In fact you might even be able to implement a "message ocx" that performs the above functionality. Dim the ocx in a public variable, then anyone that wants to send messages just calls the ocx's message method passing the params. Anyone wanting to listen to the message channel dims a local (to the form or class) variable to hold a pointer to a message OCX, then sets that pointer to point to the already initialized global message ocx. Sink it's events in this class and form and watch for messages. Anyway, this is overly long and perhaps not at all interesting, but after the thread today about withevents I thought I'd throw it out there. In fact, I just went looking and all of the code for the message class is available in a demo on our web site. Click on my last many to many article - May 2002 - Combining Withevents and RaiseEvents. At the top of the article is a link to Demo. Download the demo and watch three forms send and receive messages on a message channel using exactly the process described above. John W. Colby Colby Consulting www.ColbyConsulting.com _______________________________________________ AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com _______________________________________________ AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com