Has anyone looked at how Tapestry solved this problem?  I know they
did some work to make sure reloading happened in a "smart" way.

On Thu, Nov 18, 2010 at 10:44 AM, Igor Vaynberg <igor.vaynb...@gmail.com> wrote:
> 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
>>
>

Reply via email to