On Thu, Apr 28, 2011 at 11:30 PM, Emmanuel Lecharny <[email protected]>wrote:
> On 4/28/11 10:19 PM, Alex Karasulu wrote: > >> On Thu, Apr 28, 2011 at 2:39 PM, Kiran Ayyagari<[email protected] >> >wrote: >> >> On Thu, Apr 28, 2011 at 4:38 PM, Emmanuel Lecharny<[email protected]> >>> wrote: >>> >>>> Hi guys, >>>> >>>> yesterday, as I started to write the doc about the Search Operation, I >>>> >>> faced >>> >>>> some issue. Let me explain. >>>> >>>> When you do a simple search, you get back a cursor : >>>> >>>> SearchCursor cursor = connection.search( "ou=system", >>>> "(objectclass=*)", SearchScope.ONELEVEL ); >>>> >>>> The SearchCursor extends Cursor<Response>. >>>> >>>> That means you get some Response when you do a search, so you have to >>>> >>> write >>> >>>> such code to get back the entries : >>>> >>>> while ( cursor.next() ) >>>> { >>>> Entry entry = ((SearchResultEntry)(cursor.get())).getEntry(); >>>> >>>> which is just horrible. >>>> >>>> The reason is that the search can return three kinds of responses : >>>> - normal entries >>>> - search result done >>>> - and referrals >>>> >>>> there is one more, the IntermediateResponse >>> >>> We can deal with the searchResultDone (and we do, you can call a >>>> cursor.getSearchResultDone() when you quit the loop), but the referral >>>> handling is a bit more special. >>>> >>>> We have many options to clean up the API here : >>>> - first, we can consider that a cursor.get() will always return an entry >>>> >>> (or >>> >>>> a SearchResultEntry). In this case, if the next result is a referral, we >>>> have two cases. The first one, if the users have asked the API to chase >>>> referrals, he will get back an entry, and we are fine. The other case is >>>> when we don't chase referrals, and then we can just throw a >>>> ReferralException, up to the client to catch this exception >>>> >>> IMHO a cursor, should never assume about the type of elements it is >>> serving beyond a certain level of abstraction >>> (sadly in LDAP, as we know, the result set contains different types >>> of objects for the same operation, >>> But we have already made some changes in this way, like getting the >>> SearchResultDone) >>> >>>> - second, we can expect the user to check the result type before >>>> grabbing >>>> it. If it's a SearchResultEntry, then do a cursor.getEntry(), otherwise >>>> >>> do a >>> >>>> cursor.getReferral(). >>>> >>> this is exactly the way we wanted it to work, not just for referrals >>> but any sort of search response, >>> i.e the cursor returns the ResponseS (the super type) and it is upto >>> the user to deal based on the specific subtype >>> infact the above shown code snippet casts directly to a >>> SearchResultEntry cause we know first hand that this search >>> (perhaps done in a test case) will *only* return search entries and >>> nothing else. >>> >>> - third, we can cumulate all the referrals and ask the user to look on >>>> >>> the >>> >>>> cursor a second time to deal with referral. We would have to store those >>>> referrals internally to the cursor, and add a nextReferral() method. >>>> >>>> IMO, this should be avoided by all means, cause in the worst case it >>> will lead to a OOM >>> >>> I personally find the first solution the least painful for our users. In >>>> >>> any >>> >>>> case, we have to do two things : >>>> - change the current API >>>> - implement the Referral chasing in the API >>>> >>>> So, now, wdyt ? >>>> >>> my preference would be to keep the get() method as it is and add new >>> method(s) like getEntry() , getReferral() >>> and user can call the respective method based on his requirement, and >>> these method can throw >>> an exception when the expected type is not compatible >>> e.x NotAnEntryException when getEntry() is called but the current >>> result is a referral >>> >>> >>> And so that leads to the need for checks to see what kind of object we >> have >> the cursor currently positioned under: >> >> isEntry() >> isReferral() >> isIntermediate() >> >> This is probably best. I agree with Kiran that keeping around referral >> objects and returning them in the end is not good from a memory >> perspective. >> But if I remember correctly according to the protocol, an LDAP server does >> this automatically: meaning it's supposed to return the referrals at the >> end >> after returning regular entries. >> >> Someone please let me know if this is the case. Have not had the time to >> look this up. >> > > We reached a bit different conclusion, following Stefan's suggestions which > sounds good. For the record : > - the search( SearchRequest ) operation will return a SearchCursor, and it > will be up to the (advanced) user to deal with the different response types > (SearchResultEntry, SearchResultReferral and IntermediateResponse) > - any other search will return an EntryCursor. > - the SearchResutDone result will just be managed when we get out of the > loop > - we can add the isEntry(), isReferral() and isIntermediate() methods, in > addition to the getEntry(), getReferral() and getIntermediate() methods in > the SearchCursor interface > > That sounds to be a good compromise, as of today. > > Yeah I recommend taking our time with this. This is a big change. Maybe we can experiment with it a little and see how test client code looks when using the different approaches. I would be really careful with this since it's pretty much the biggest operation of all :-). Regards, Alex
