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:
unthreadedExists
unthreadedReadEntry
unthreadedCopy
unthreadeList
unthreadedModify
unthreadedSearch
unthreadedGetAllOCs
unthreadedGetRecOCs
(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:
-
Check the existence of an entry
-
If it doesn't exist, create it (and a subtree)
-
If it does, check the subtree exists (and create it if it doesn't)
-
copy everything to a backup branch.
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())
}
}