invoking a constructor on a constructed class can lead to a lot more weirder state problems. dont forget, constructors dont just add class, they initialize state. invoking the constructor itself is not enough, you also need to invoke field initializations that are inlined, etc. at that point you might as well create a new instance of the page - since that is what you are essentially doing.
-igor On Thu, Nov 18, 2010 at 4:52 AM, Martijn Dashorst <martijn.dasho...@gmail.com> wrote: > I've been trying out jrebel and wicket a couple of times, and I > thought it didn't work. It does, but the way Wicket development works > is undoing most of the benefits of using jrebel. > > The idea of jrebel is to replace hotswap with something that actually > works for normal development: adding methods, renaming them, creating > new (anonymous inner) classes etc, without having to restart your > application. And that works quite well... > > Until you start developing with Wicket. > > The problem is that our component hierarchy doesn't work well with > code replacement. A typical workflow is that you navigate in your > application to a page, and want to add a new component to it. So you > go into that class: > > public class LinkCounter extends WebPage { > public LinkCounter() { > } > } > > add a field: > > private int counter; > > add a label: > > public LinkCounter() { > add(new Label("counter", new PropertyModel<Integer>(this, "counter))); > } > > <span wicket:id="counter"></span> > > add a link: > > public LinkCounter() { > ... > add(new Link<Void>("click") { > public void onClick() { > counter++; > }); > } > } > > <a href="#" wicket:id="click">Click me</a> > > All is well, and when you refresh the page (as long as you had a > bookmarkable link to it) it shows the new label and link. You click > the link and the URL changes from a bookmarkable URL to a link to a > specific instance. > > Now you want to add another link: > > add(new Link<Void>("minus") { > public void onClick() { > counter--; > } > }); > > Don't forget to modify the markup: > <span wicket:id="minus"></span> > > JRebel does its thing: adding the code to the constructor including > the anonymous inner class. You refresh your page and are presented > with a component not found exception: minus is added in the markup, > but not in the java code > > The problem is that jrebel doesn't invoke the constructor (again) when > replacing the code. Moving the code to onInitialize() might enable the > jrebel plugin to call that method when it modifies a component class. > This won't work because you typically then get: > > java.lang.IllegalArgumentException: A child with id 'counter' > already exists: > > Now we could ask folks to use addOrReplace() instead of add(), or we > could relax the multi add restriction to alleviate this problem. > > I wouldn't be against relaxing add() and deprecating addOrReplace(). > > Now calling onInitialize again on a constructed component might open > up another can of worms. > > Is this something worth pursuing? Or should we just write an article > with how to do jrebel no-redeploy wicket coding? > > Martijn >