The Collector Client

I propose that we build a VB client that uses ADO for the ordinary database access and the MSMQ ActiveX objects for the message queuing, plus our own ATL-developed transactional object for the transfer. This is what our VB application’s form looks like:

The top section of the form contains a list of all the Beanie Babies that this client is currently actively looking for. This is constructed by going through all the Beanie Babies in his or her database, and extracting the names of all those with the “wanted” bit set. If we’re about to give up looking for one of them, we click on the Offer button, which adds it to the queue of those available for others to take over the search. If we actually find one of them, we click on the Got button. This clears the “Wanted” bit on the record, and it disappears from the list. If we made a mistake with one of the names, we can delete it altogether by clicking on the Delete button.

The text box in the middle, and the Add button are used to enter names for new Beanie Babies. These immediately become wanted, and are added to our list. There isn’t, incidentally, a mechanism to ensure that the same Beanie Baby is added to several people’s databases at the same time – a small flaw in the system.

The bottom section of the form is used if we want to take over the search for a Beanie Baby from someone else – say, for example, if we’ve just found a really good supplier that has got lots of really rare ones. We select a specific machine's queue to look at by means of the combo box at the bottom, and the list of Beanie Babies that are currently on that queue appears in the list box above. If we select one, and click on the Take button, it moves over to our database; this is the transactional stuff.

So, from the point of view of one node connected to the offered queue, this is where the information is moved from and to:

Here’s an example in practice:

Here, our client (on node dipsy), is already actively looking for Britannia, Doby, Hoot and so on. Our colleague on node tinky-winky, meanwhile, has given up looking for Lefty, Righty and Princess and is offering the search opportunity to others. If we happen to know of a place where we can get hold of a Princess, for instance (and I’m not telling you where our daughter got hers from), we could choose to take Princess off the queue and put it into our database.

OK, what does the code look like?

This is the VB code for the routine that refreshes the “wanted” list:

Private Sub RefreshWanted()
    lstWanted.Clear

    Dim conn As ADODB.Connection
    Set conn = New Connection
    conn.Open dbopen

    Dim rs As ADOR.Recordset
    Set rs = New Recordset

    rs.Open "checklist", conn, adOpenForwardOnly, adLockPessimistic, _
            adCmdTable

    Dim fields As ADODB.fields
    Dim field As ADODB.field
    Dim name As String
    Dim want As Boolean
       
    Do While Not rs.EOF
        Set fields = rs.fields
    
        For Each field In fields
            If field.name = "description" Then
                name = field.Value
            ElseIf field.name = "wanted" Then
                want = field.Value
            End If
        Next field
    
        ' Only add wanted items to the list
        If want Then
            lstWanted.AddItem Trim(name)
        End If
        rs.MoveNext
    Loop
    
    Set fields = Nothing
    Set rs = Nothing
    Set conn = Nothing

End Sub

Notice how ADO makes walking sequentially through a database really very straightforward. Now let’s see some of the message queue handling code. This is the bit that outputs the contents of a queue, when the combo box at the bottom is selected:

Private Sub cmbQueueList_Click()
    lstOffered.Clear

    Dim info As New MSMQQueueInfo
    info.PathName = cmbQueueList.Text

    Dim q As MSMQQueue
    Set q = info.Open(MSMQ.MQ_PEEK_ACCESS, MSMQ.MQ_DENY_NONE)

    Dim message As MSMQMessage
    Set message = q.PeekCurrent(, , 100)

    Do While Not message Is Nothing
        lstOffered.AddItem message.Label
        Set message = q.PeekNext(, , 100)
    Loop
End Sub

All of which bears a considerable resemblance to the MFC stuff in our earlier e-mail example (except ever so slightly cleaner). Once again, it’s a question of peeking through our queue, picking off all the labels. Incidentally, our messages here have no body — they’re just a label.

Now we get to the interesting bit. This is what happens when we click the Offer button:

Private Sub cmdOffer_Click()
    Dim count As Integer
    Dim index As Integer

    count = lstWanted.ListCount

    For index = 0 To count - 1
        If (lstWanted.Selected(index)) Then
            Dim item As String
            item = lstWanted.List(index)
    
            Dim xfer As Transfer
            Set xfer = New Transfer
            xfer.PutOnQueue item
        End If
    Next index

    RefreshWanted
End Sub

The critical part here is where we instantiate a Transfer object, and invoke the PutOnQueue() method. This Transfer object is running under MTS, so we’re going to be doing some transactional maneuvers. This is where we get to do some ATL work (Ah! Real programming at last!). I won’t show you the rest of the VB stuff here, but if you want it, it’s available for download from www.wrox.com.

© 1998 by Wrox Press. All rights reserved.