Return-Path: X-Original-To: apmail-directory-dev-archive@www.apache.org Delivered-To: apmail-directory-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 0E7693BF7 for ; Thu, 28 Apr 2011 12:32:20 +0000 (UTC) Received: (qmail 17553 invoked by uid 500); 28 Apr 2011 12:32:19 -0000 Delivered-To: apmail-directory-dev-archive@directory.apache.org Received: (qmail 17515 invoked by uid 500); 28 Apr 2011 12:32:19 -0000 Mailing-List: contact dev-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Apache Directory Developers List" Delivered-To: mailing list dev@directory.apache.org Received: (qmail 17507 invoked by uid 99); 28 Apr 2011 12:32:19 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 28 Apr 2011 12:32:19 +0000 X-ASF-Spam-Status: No, hits=-0.7 required=5.0 tests=FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,RFC_ABUSE_POST,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of ayyagarikiran@gmail.com designates 209.85.212.50 as permitted sender) Received: from [209.85.212.50] (HELO mail-vw0-f50.google.com) (209.85.212.50) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 28 Apr 2011 12:32:14 +0000 Received: by vws14 with SMTP id 14so2449605vws.37 for ; Thu, 28 Apr 2011 05:31:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:content-type :content-transfer-encoding; bh=i4nKGomcjiJ/zYyr7XoyFbB29ndvi7wGxWtWe4hpS9k=; b=r4SLSfZVaLqZgo1uyTE6fESwnRoRgMbGm7Gcg3frPF8xbmzMq4U8lXpjIp6qJsId1Q N1pYN1XE8lBnD3Jozx2oIjEravVddmglo3MRveiX4WDaHc9EBJUeBsx43/+3rw4cwBUa +qiSBx1i5AbEv+SVfjF4VRoRtV/+0bmJt3R90= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:content-type :content-transfer-encoding; b=dEyfeAB1E36B73loPvFZmvcn/pQLzq9j+eJP+h5cVDlNOJKkh6a8R0RdlfWn0cKd4p RaKQrgIpUUiDfHe6MaeuF6Osfhkgy485L+Pv8tlzFpVIMt2lJ1o47RVXh7NFtZVFSPtE KHpPCqXbmpEU7BsNZWfgsLlUWzpvi0dOFUbmQ= MIME-Version: 1.0 Received: by 10.52.96.8 with SMTP id do8mr5015402vdb.142.1303993913167; Thu, 28 Apr 2011 05:31:53 -0700 (PDT) Sender: ayyagarikiran@gmail.com Received: by 10.52.164.10 with HTTP; Thu, 28 Apr 2011 05:31:53 -0700 (PDT) In-Reply-To: <4F5C26AF-2E6A-442C-A694-097C3851A62B@marcelot.net> References: <4DB94AA0.5030302@gmail.com> <4F5C26AF-2E6A-442C-A694-097C3851A62B@marcelot.net> Date: Thu, 28 Apr 2011 18:01:53 +0530 X-Google-Sender-Auth: xecR4pDyWKIZ2Uq1f4xlmLbxG2w Message-ID: Subject: Re: Search result in LDAP API From: Kiran Ayyagari To: Apache Directory Developers List Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On Thu, Apr 28, 2011 at 5:50 PM, Pierre-Arnaud Marcelot w= rote: > > On 28 avr. 2011, at 13:39, Kiran Ayyagari wrote: > >> On Thu, Apr 28, 2011 at 4:38 PM, Emmanuel Lecharny = 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 : >>> >>> =A0 =A0 =A0 =A0SearchCursor cursor =3D connection.search( "ou=3Dsystem"= , >>> "(objectclass=3D*)", SearchScope.ONELEVEL ); >>> >>> The SearchCursor extends Cursor. >>> >>> That means you get some Response when you do a search, so you have to w= rite >>> such code to get back the entries : >>> >>> =A0 =A0 =A0 =A0while ( cursor.next() ) >>> =A0 =A0 =A0 =A0{ >>> =A0 =A0 =A0 =A0 =A0 =A0Entry entry =3D ((SearchResultEntry)(cursor.get(= ))).getEntry(); >>> >>> which is just horrible. > > I completely agree. > We are creating this API to make the user's life easier and not embarrass= him with such constructions. > I'm pretty sure 90% of the users of the API won't know there are multiple= types of responses to search. > Most of them only expect entries. > > On the other hand, LDAP experts know everything about the spec and the AP= I should also ease their work and allow them to access everything. > >>> 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 entr= y (or >>> a SearchResultEntry). In this case, if the next result is a referral, w= e >>> 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 i= s >>> 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 grabbi= ng >>> 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 thos= e >>> 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. I= n 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 > > This would be my preference as well (with another method to access the In= termediateResponse too). > > But I would add other convenient methods like: > - boolean nextEntry(); > - boolean nextReferral(); > - boolean nextIntermediate(); hmm, we can just use next() method alone, cause all that we need is to read the next response (OTOH nextEntry/Referral() might confuse users to think that the cursor will skip to next avalable entry in the responses) > - boolean previousEntry(); > - boolean previousReferral(); > - boolean previousIntermediate(); we cannot support these methods unless we store them in the cursor, but as we know, maintaining them in memory brings up other issues (GC, OOM) > This methods would allow the user to jump to the next/previous object of = their choice easily. > > For example, this snippet would allow the user to get all entries from a = search cursor in a much nicer way than today: >> while ( cursor.nextEntry() ) we can just use - while ( cursor.next() ) >> { >> =A0 =A0 =A0 Entry entry =3D cursor.getEntry(); >> } > > Other methods to know what is the type of the current object in the curso= r would also be useful like: > - boolean isCurrentEntry(); > - boolean isCurrentReferral(); > - boolean isCurrentIntermediate(); +1, makes it more convenient > > Lastly, I'm wondering if the getXXX() methods should return an Entry/Refe= rral or the associated SearchResult instead (SearchResultEntry/SearchResult= Reference). > Thoughts? > just the plain Entry/Referral/IntermediateResponse objects directly, otherwise caller has to make another call like SearchResultEntry.getEntry() --=20 Kiran Ayyagari