I’ve struck a problem with Java and Apache Wicket 1.5 where the identity of the enclosing Java object for two anonymous classes has changed!
Within one Wicket modal window I want to create a second modal window (for getting a text string prompt) and then update the original modal window with an AJAX refresh of the model (a list of string-integer pairs).
Basically I have two anonymous classes created in the same method but the ‘this’ pointer for the enclosing instance is different between one anonymous class and the other.
This does not seem like normal expected JVM behavior to me but I haven’t been able to find any specifics of how this works in the Java Specification either.
public class DropDownChoiceModal extends WebPage {
public String newTermResponse;
private void addAddTermModal() {
addTermModal = new ModalWindow("add_term_modal");
addTermModal.setPageCreator(new ModalWindow.PageCreator() {
public Page createPage() {
PropertyModel pm = new PropertyModel<String>(DropDownChoiceModal.this, "newTermResponse");
System.out.println ("propModel: " + System.identityHashCode(DropDownChoiceModal.this));
return new TextInputModal(addTermModal, "What is the new term you wish to add?", pm);
}
});
addTermModal.setWindowClosedCallback(new WindowClosedCallback() {
public void onClose(AjaxRequestTarget target) {
System.out.println ("propModel: " + System.identityHashCode(DropDownChoiceModal.this));
System.out.println ("newTermResponse: " + DropDownChoiceModal.this.newTermResponse);
// If the value is set then use it
if (newTermAvailable()) {
// Add the new term to the model
model.add(new StringIntegerPair (newTermResponse, 0));
System.out.println ("Update view: " + model.size());
// Update the view
target.add(wmc);
}
System.out.println ("No new term");
}
private boolean newTermAvailable() {
return (newTermResponse != null) && !newTermResponse.isEmpty();
}
});
add(addTermModal);
}
For the TextInputModal class:
public class TextInputModal extends WebPage {
public TextInputModal(final ModalWindow modal, String requestString, final IModel<?> model) {
Form<String> form = new Form<String>("form") {
public void onSubmit() {
System.out.println ("Submitted: " + System.identityHashCode(((PropertyModel)model).getTarget()) + "; " + model.getObject());
}
};
// Add the buttons
form.add(new AjaxButton("ok") {
public void onAfterSubmit(AjaxRequestTarget target, Form<?> form) {
System.out.println ("Submitted 2: " + System.identityHashCode(((PropertyModel)model).getTarget()) + "; " + model.getObject());
modal.close(target);
}
});
// Add the form
add(form);
}
}
The output I get:
propModel: 698650686
Submitted: 698650686; fdsfds
Submitted 2: 698650686; fdsfds
propModel: 1447892364
newTermResponse: null
No new term
Any ideas why the identity of the enclosing instance (DropDownChoiceModal.this) has changed between anonymous class 1 ( new ModalWindow.PageCreator() {} ) and anonymous class 2 ( new WindowClosedCallback() {} ) when they are created in the same method ( addAddTermModal() )?
Thanks in advance…
Nigel
Big thanks to biziclop in the comments above… it looks like Wicket was clobbering the object when it was getting serialized – the contents of the “newTermResponse” String were getting lost somewhere during this serialization.
I went back to the example of nested ModalWindow’s here:
http://www.wicket-library.com/wicket-examples/ajax/modal-window
Using getPageReference() as shown in the example instead of PropertyModel solved my issue.
Cheers,
Nigel