Writing Connection Thread Code

Bundling Complex Directory Code

If you have a complex piece of directory logic to execute, the preceding methods may be a bit clumsy. For example, consider the action "check if this entry exists, if it doesn't create the following sub tree, otherwise check that all these components exist, and if they don't create them, and finally copy the whole tree into a backup branch directory". This could be done using the previous technique by doing the first query (an existence check) and then putting the rest of the code in the DataListener, while using the DataQueries 'getBroker()' method.

A neater way of doing it however is to bundle all the code up in one place, and use an 'extended data query'. The method is simply to extend the DataQuery class by implementing the 'doExtendedRequest()' method, and then pass the resulting query to the connection thread using the broker's 'extendedQuery()' method.

For Example...

The code in the previous chapter (which read an entry and printed it out) could be rewritten as:



public class MyPluggableEditor extends BasicPluggableEditor
{
...
...

    public void displayEntry(DXEntry entry, DataSource myDataSource)
    {
    ...
    ...
    

        myDataSource.extendedRequest(new DataQuery
        {
            public void doExtendedRequest(Broker myBroker)
            {
                DXEntry myEntry = myBroker.unthreadedReadEntry(
                                   new DN("cn=fred,ou=R&D,o=CA")); 
                                                  
                if (myBroker.getException() != null)
                {
                     System.err.println("couldn't read entry " 
                     + query.getDN() + "\nexception was: " + 
                     query.getException());
                }
                else
                {
                     System.out.println("read entry " + 
                                            query.getEntry());
                }

            }
       });
       
        
    }
}             

(Note that there is no need to 'squelch()' anything, since no listeners (except any that you might register) pay any attention to extended queries).

Unthreaded Broker Methods

Since the DataQuery is being run in the connection thread, it should use the 'unthreaded' broker methods to access the directory. These are:

(Check the API doco for details)

Warning!

Use of the threaded methods (such as doEntryQuery() instead of unthreadedRead() ) can end in disaster. The threaded methods place a query on the connection thread queue. Since the extended request is being run by this same connection thread, if our code tries to read the result of one of these threaded operations, the connection thread will immediately deadlock.

A More Complex Example

As a more elaborate example, let's try the scenario outlined above:


public class MyPluggableEditor extends BasicPluggableEditor
{
...
...
    public void displayEntry(DXEntry entry, DataSource myDataSource)
    {
    ...
    ... 
        /**
         *   Define a new 'ExtendedDataQuery' class.
         *   (XXX error checking not implemented)
         */             
        
 
        class ExtendedDataQuery extends DataQuery
        {
            Broker currentBroker = null;
            public void doExtendedRequest(Broker myBroker)
            {
                currentBroker = myBroker;
                boolean exists = currentBroker.unthreadedExists(
                                                new DN("cn=top,o=CA"));
                if (exists == false) 
                {
                    writeTop();
                    writeTree();
                }
                else
                {
                    if (checkTree() == false)
                    writeTree()
                }                         
                currentBroker.unthreadedCopy(new DN("cn=top,o=CA"), 
                                    new DN("cn=top,cn=backup,o=CA"));
            }
            void writeTop()
            {
                DXEntry top = new DXEntry("cn=top,o=CA");
                top.put("objectClass", "TopEntry");
                currentBroker.unthreadedModify(null, top);
            }
            void writeTree()
            {
                DXEntry[] nodes = new DXEntry[5];
                DXEntry[0] = new DXEntry("cn=node A,cn=top,o=CA");
                DXEntry[1] = new DXEntry("cn=node B,cn=top,o=CA");
                DXEntry[2] = new DXEntry("cn=node C,cn=top,o=CA");
                DXEntry[3] = new DXEntry("cn=node D,cn=top,o=CA");
                DXEntry[4] = new DXEntry("cn=node E,cn=top,o=CA");
                for (int i=0; i<5; i++)
                {
                    DXEntry[i].put("objectClass", "TreeEntry");
                    currentBroker.unthreadedModify(null, DXEntry[i]);
                }    
            }
            boolean checkTree()
            {
                DXNamingEnumeration list = 
                        currentBroker.unthreadedList("cn=top,o=CA");
                return (list != null && list.size() == 5);
            }
        }
        ...    
        //   Create and run our extended query.        
        myDataSource.extendedRequest(new ExtendedDataQuery())
                
    }
}

» top