Hi all, I agree with Joe's remark too. I have made the change locally to the Resource and Handler classes. I will check that in when I'm done with the Resource refactoring.
We won't port that change back to 1.0 as it slightly modifies the API contract. Best regards, Jerome > -----Message d'origine----- > De : Thierry Boileau [mailto:[EMAIL PROTECTED] > Envoyé : mardi 23 octobre 2007 17:09 > À : [email protected] > Objet : Re: When and when not to override Resource.init > > Thanks a lot Joe for this nice demonstration! > I'm totally convinced. I think also the init method must be removed > from the "normal" constructor. > > best regards, > Thierry Boileau > > On 10/22/07, Joe Nellis <[EMAIL PROTECTED]> wrote: > > Ok, well I just want to make sure you know what I'm talking about. I > > understand the need to have a default constructor for > injection purposes but > > that is not the issue. The issue is with the "normal" > constructor calling > > init. It should not call init. It might be convenient to > put all the > > context, request, response object assignments in init for > the Spring folk > > but it needs to be duplicated in the "normal" constructor > also, instead of > > just calling init. You must never call non-final methods inside a > > constructor.. Here is some test code that explains the bug. > > > > package test; > > > > import org.restlet.Context; > > import org.restlet.data.MediaType; > > import org.restlet.data.Request; > > import org.restlet.data.Response; > > import org.restlet.resource.Representation; > > import org.restlet.resource.Resource; > > import org.restlet.resource.StringRepresentation; > > import org.restlet.resource.Variant; > > > > /** > > * > > * @author jnellis > > */ > > public class MyResource extends Resource{ > > // These variables get initialized AFTER init is called! > > private String something = "default-value"; > > private String other; // no default initializer, the > default is null. > > > > public MyResource(){ > > // You can provide this constructor but a Finder won't > look at it > > // because of the "normal" constructor. > > } > > > > public MyResource(Context context, Request request, > Response response){ > > // The call to super happens before the construction of > THIS subclass > > // object and so when it calls init, it is really > calling a method > > // of an object that has not been initialized. > > super(context,request,response); > > } > > > > @Override > > public void init(Context context, Request request, > Response response){ > > // call first as Resource.init documentation says. > > super.init(context,request,response); > > > > // Now do our initialization stuff. > > // The only safe operations are on direct members of > the Resource > > // class itself, mainly, it seems, to be able to add > Variants this > > // resource handles. > > getVariants().add(new Variant(MediaType.TEXT_PLAIN)); > > > > /* The developer says to himself, "oh hey, this is a > nice place to > > * put my subclass specific stuff too!" BAM! problems > start here. > > */ > > this.something = "apples"; > > this.other = "oranges"; > > } > > > > @Override > > public Representation getRepresentation(Variant variant){ > > Representation result = null; > > // One would think this prints "apples or oranges" but > on my machine > > // it prints out "default-value or oranges". > > result = new StringRepresentation(something + " or " + other); > > // ANY subclass variable with a default initializer will end up > > // re-initializing that variable after it has been set in > > // the init method. > > return result; > > } > > } > > > > > > > > > > > > ----- Original Message ----- > > From: "Thierry Boileau" <[EMAIL PROTECTED]> > > To: <[email protected]> > > Sent: Monday, October 22, 2007 5:02 AM > > Subject: Re: When and when not to override Resource.init > > > > > > > Hello Joe, > > > > > > The "init" method has been introduced in order to satisfy > recurrent > > > requests made by Spring users of the Restlet framework. There is a > > > need to create resources with the default constructor, > instead of the > > > "normal" one (the one with the 3 parameters). On the other hand > > > resources need to be instantiated with their context plus > the request > > > and response objects. That's why the Finder tries to invoke the 3 > > > parameters constructor, and if it doesn' exist, invokes > the default > > > constructor then the "init" method. > > > Having said that, I'm conscious that I've uncompletely answered to > > > your question... But I've a meeting right now. > > > > > > best regards, > > > Thierry Boileau > > > > > > On 10/22/07, Joe Nellis <[EMAIL PROTECTED]> wrote: > > >> Greetings, > > >> > > >> This purposefully overridable method is called from the > Resource(Context, > > >> Request, Response) constructor and therefore subclasses > that override > > >> init(Context, Request, Response) are in for a big > suprise if they try to > > >> do > > >> operations on their own fields in the init method. At > this point in > > >> execution, the subclass of Resource has not been > initialized and so > > >> default > > >> field intializers have not been called, not even fields > declared final. > > >> The > > >> default initializers will be called after init finishes > and any subclass > > >> fields set during the init method call will be > overwritten with defaults. > > >> This is a gotcha in Joshua Blochs Effective Java pg 80. > Constructors of > > >> classes intended to be subclassed should not call > overridable methods. > > >> > > >> So I think some clarification on when to override init > when your class > > >> also > > >> supports the three argument resource constructor > (assuming you call > > >> super(context,request,response) first in the > constructor.) Why is there > > >> a > > >> three argument constructor? The Finder.createResource > calls the default > > >> constructor then calls init afterwards which is ok > because all subclasses > > >> have been initialized by then. > > >> > > >> Perhaps there is a way with annotations to convey > Variants a resource has > > >> representations for as this is what the init method > seems to be of value > > >> for, adding variants to the list. > > >> > > >> -Joe > > >> > >

