You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by "Jablow, Eric R" <Er...@ManTech.com> on 2011/11/18 01:05:49 UTC

ValidationForm.addPropertyValidators sometimes looks for child properties in parent's model

I have some model classes with JSR 303 validation annotations, and I have some FormComponentPanels for each. Some of these will be nested. To test that the Wicket validation is correct, I'm creating a ValidationForm, which contains one of my panels, which contains another of my panels, and I am tying my form to a local minimal test object without the other fields I will be using later. I am using a CompoundPropertyModel. When I have the WicketTester initialize the ValidationForm, it looks for the 'parent' field in the minimal test object, which does exist.  Then, I get at line 302 of AbstractPropertyModel,

      return PropertyResolver.getPropertyGetter(expression, target);

I get a call with expression being "child", and target being the local test object.  Were expression "parent.child", this would succeed, as it would call getParent().getChild(). However, I'm not sure whether this is my bug or the wicket-validation-bean library's.

Incidentally, I'm getting an interesting misfeature from the validation; the order in which the validations are performed seems to be nondeterministic. This means that the test below fails sometimes.

                tester.assertFeedback("path:to:panel", new String[] {messageA, messageB});

Often, when I reverse the order of messageA and messageB, the next test fails too! Perhaps Wicket 1.5.3 can have WicketTester.assertFeedback(String path, Set<String> messages).

Finally, I might need to avoid FormComponentPanels in the future, as some of the inner ones will be swapped in and out of the page depending on the user's choices.  I realize that the only panels that will be instrumented are the ones in the Form when it is originally configured.

Thanks in advance.

Respectfully,
Eric Jablow

This communication, along with any attachments, is covered by federal and state law governing electronic communications and may contain company proprietary and legally privileged information.  If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution, use or copying of this message is strictly prohibited.  If you have received this in error, please reply immediately to the sender and delete this message.  Thank you.

Re: ValidationForm.addPropertyValidators sometimes looks for child properties in parent's model

Posted by Igor Vaynberg <ig...@gmail.com>.
its very hard to figure out problems like this without having running
code. you can either create a quickstart with a failing testcase, or
even better make a pull request on github that will add the failing
testcase directly into the codebase.

thanks,
-igor

On Mon, Nov 21, 2011 at 12:34 PM, Jablow, Eric R
<Er...@mantech.com> wrote:
>
> Igor>but you can create a testcase, reproducing the bare bits of code in a
> testcase just like you did in the email below. the advantage would be
> that i would have something i can play with which makes it much easier
> to find the problem.
>
> I will work on a quick start tonight, when I'm not at work. But here's what I'd like to do, possibly extending Metagen. I have a Report object which includes an abstract Document object.  Document has 3 concrete subclasses, Book, Article, and Monograph. I have FormComponentPanels for each, which I'd like to swap in and out. I've used Metagen to create ReportMeta, DocumentMeta, BookMeta, etc.  I'd like to extend Metagen so I can write code like
>
> IModel<Book> bookModel = MetaModel.of(report).get(ReportMeta.document).as(Book.class);
>
> and
>
> IModel<String> isbnModel = MetaModel.of(report).get(ReportMeta.document).as(Book.class).get(BookMeta.isbn);
>
> Since I don't want to modify the MetaModel class on my own, I've written a SubClassModel class like so:
>
>        private static class SubClassModel<T> extends MetaModel<T> {
>                private static final long serialVersionUID = 3511732306311269529L;
>
>                public SubClassModel(MetaModel<? super T> superModel, Class<T> clazz) {
>                        super(superModel);
>                }
>
>                @Override
>                public T getObject() {
>                        return (T) super.getObject();
>                }
>                @Override
>                public void detach() {
>                        super.detach();
>                }
>
>                public static <T> MetaModel<T> as(MetaModel<? super T> superModel, Class<T> clazz) {
>                        return new SubClassModel<T>(superModel, clazz);
>                }
>        }
> }
>
> Unfortunately, when the validation system gets its hands on this, it throws a NPE as it adds the property validators:
>
> Caused by: java.lang.NullPointerException
>        at net.ftlines.wicket.validation.bean.ReflectableProperty.init(ReflectableProperty.java:46)
>        at net.ftlines.wicket.validation.bean.ReflectableProperty.<init>(ReflectableProperty.java:98)
>        at net.ftlines.wicket.validation.bean.ModelPropertyResolver.resolve(ModelPropertyResolver.java:35)
>        at net.ftlines.wicket.validation.bean.ValidationContext.resolveProperty(ValidationContext.java:80)
>        at net.ftlines.wicket.validation.bean.ValidationForm$1.component(ValidationForm.java:170)
>        at net.ftlines.wicket.validation.bean.ValidationForm$1.component(ValidationForm.java:163)
>        at org.apache.wicket.util.visit.Visits.visitChildren(Visits.java:143)
>        at org.apache.wicket.util.visit.Visits.visitChildren(Visits.java:161)
>        at org.apache.wicket.util.visit.Visits.visitChildren(Visits.java:122)
>        at org.apache.wicket.MarkupContainer.visitChildren(MarkupContainer.java:908)
>        at net.ftlines.wicket.validation.bean.ValidationForm.addPropertyValidators(ValidationForm.java:162)
>        at net.ftlines.wicket.validation.bean.ValidationForm.onBeforeRender(ValidationForm.java:155)
>        at org.apache.wicket.Component.internalBeforeRender(Component.java:981)
>        at org.apache.wicket.Component.beforeRender(Component.java:1015)
>        at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1785)
>        ... 52 more
>
> This happens when Model is that SubclassModel<Book>.
>
> How would you use Metagen for this case?  Is it worth extending it?
>
> Respectfully,
> Eric Jablow
>
> This communication, along with any attachments, is covered by federal and state law governing electronic communications and may contain company proprietary and legally privileged information.  If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution, use or copying of this message is strictly prohibited.  If you have received this in error, please reply immediately to the sender and delete this message.  Thank you.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: ValidationForm.addPropertyValidators sometimes looks for child properties in parent's model

Posted by "Jablow, Eric R" <Er...@ManTech.com>.
Igor>but you can create a testcase, reproducing the bare bits of code in a
testcase just like you did in the email below. the advantage would be
that i would have something i can play with which makes it much easier
to find the problem.

I will work on a quick start tonight, when I'm not at work. But here's what I'd like to do, possibly extending Metagen. I have a Report object which includes an abstract Document object.  Document has 3 concrete subclasses, Book, Article, and Monograph. I have FormComponentPanels for each, which I'd like to swap in and out. I've used Metagen to create ReportMeta, DocumentMeta, BookMeta, etc.  I'd like to extend Metagen so I can write code like

IModel<Book> bookModel = MetaModel.of(report).get(ReportMeta.document).as(Book.class);

and

IModel<String> isbnModel = MetaModel.of(report).get(ReportMeta.document).as(Book.class).get(BookMeta.isbn);

Since I don't want to modify the MetaModel class on my own, I've written a SubClassModel class like so:

	private static class SubClassModel<T> extends MetaModel<T> {
		private static final long serialVersionUID = 3511732306311269529L;

		public SubClassModel(MetaModel<? super T> superModel, Class<T> clazz) {
			super(superModel);
		}

		@Override
		public T getObject() {
			return (T) super.getObject();
		}
		@Override
		public void detach() {
			super.detach();
		}

		public static <T> MetaModel<T> as(MetaModel<? super T> superModel, Class<T> clazz) {
			return new SubClassModel<T>(superModel, clazz);
		}
	}
}

Unfortunately, when the validation system gets its hands on this, it throws a NPE as it adds the property validators:

Caused by: java.lang.NullPointerException
	at net.ftlines.wicket.validation.bean.ReflectableProperty.init(ReflectableProperty.java:46)
	at net.ftlines.wicket.validation.bean.ReflectableProperty.<init>(ReflectableProperty.java:98)
	at net.ftlines.wicket.validation.bean.ModelPropertyResolver.resolve(ModelPropertyResolver.java:35)
	at net.ftlines.wicket.validation.bean.ValidationContext.resolveProperty(ValidationContext.java:80)
	at net.ftlines.wicket.validation.bean.ValidationForm$1.component(ValidationForm.java:170)
	at net.ftlines.wicket.validation.bean.ValidationForm$1.component(ValidationForm.java:163)
	at org.apache.wicket.util.visit.Visits.visitChildren(Visits.java:143)
	at org.apache.wicket.util.visit.Visits.visitChildren(Visits.java:161)
	at org.apache.wicket.util.visit.Visits.visitChildren(Visits.java:122)
	at org.apache.wicket.MarkupContainer.visitChildren(MarkupContainer.java:908)
	at net.ftlines.wicket.validation.bean.ValidationForm.addPropertyValidators(ValidationForm.java:162)
	at net.ftlines.wicket.validation.bean.ValidationForm.onBeforeRender(ValidationForm.java:155)
	at org.apache.wicket.Component.internalBeforeRender(Component.java:981)
	at org.apache.wicket.Component.beforeRender(Component.java:1015)
	at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1785)
	... 52 more

This happens when Model is that SubclassModel<Book>.

How would you use Metagen for this case?  Is it worth extending it?

Respectfully,
Eric Jablow

This communication, along with any attachments, is covered by federal and state law governing electronic communications and may contain company proprietary and legally privileged information.  If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution, use or copying of this message is strictly prohibited.  If you have received this in error, please reply immediately to the sender and delete this message.  Thank you.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: ValidationForm.addPropertyValidators sometimes looks for child properties in parent's model

Posted by Igor Vaynberg <ig...@gmail.com>.
On Fri, Nov 18, 2011 at 9:32 AM, Jablow, Eric R <Er...@mantech.com> wrote:
> Dear Igor,
>
> (me)>> I get a call with expression being "child", and target being the local test object.  Were expression "parent.child", this would succeed, as it would call getParent().getChild(). However, I'm not sure whether this is my bug or the wicket-validation-bean library's.
>
> (Igor)>this is probably a misuse of the compound property model, which is
> evil anyways. you have to create your components with ids that match
> the path from the root object, so if you want to access person.address
> property you cant put a text field with id "address" into a
> webmarkupcontainer of id "person", you have to add a text field with
> component id "person.address"
>
> I'm sorry that I can't send or post the problematic code; much of it is proprietary. Here's a censored précis.

but you can create a testcase, reproducing the bare bits of code in a
testcase just like you did in the email below. the advantage would be
that i would have something i can play with which makes it much easier
to find the problem.

>
> I have a Report object for people to fill out. Report has a variable of type Publication, Publication being an interface.
>
> public class Report implements Serializable {
>        @Valid
>        private Publication publication;
> }
>
> public interface Publication extends Serializable {}
>
> public class Book implements Publication {}
> public class Article implements Publication {}
> public class Monograph implements Publication()
>
> I have UI panels:
>
> public class BookPanel extends FormComponentPanel<Book> {}
> public class ArticlePanel extends FormComponentPanel<Article> {}
> public class MonographPanel extends FormComponentPanel<Monograph> {}
>
> I'm trying to create a PublicationPanel:
>
> public class PublicationPanel extends FormComponentPanel<Publication> {
>        private RadioChoice<String> publicationTypeChoice;
>        private FormComponentPanel<? extends Publication> specificPublicationPanel;
> }
>
> I will swap a BookPanel, ArticlePanel, and MonographPanel in depending on the user's choice of type. If CompoundPropertyModels are evil (and I'd like a pointer to why),

CPMs work great when they do, but when they do not it is extremely
difficult to find out why - as you have discovered in this case. their
implicit nature makes it so. this is why they are evil.

> how can I take a IModel<Report> and turn it into a IModel<Publication> and IModel<Book>, and so on?

you have to cast it because only you know that at some point
Publication is actually a Book.

> Does the metagen project handle the polymorphism?

not in this case, just like java cant.

> Should I be using the single-argument constructor of FormComponentPanel<T> at all?

not sure. would need to see more code

> Does it matter if I need to use the PublicationPanel more than once in the ReportForm?

it shouldnt.

-igor

>
> Respectfully,
> Eric Jablow
>
> This communication, along with any attachments, is covered by federal and state law governing electronic communications and may contain company proprietary and legally privileged information.  If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution, use or copying of this message is strictly prohibited.  If you have received this in error, please reply immediately to the sender and delete this message.  Thank you.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: ValidationForm.addPropertyValidators sometimes looks for child properties in parent's model

Posted by "Jablow, Eric R" <Er...@ManTech.com>.
Dear Igor,

(me)>> I get a call with expression being "child", and target being the local test object.  Were expression "parent.child", this would succeed, as it would call getParent().getChild(). However, I'm not sure whether this is my bug or the wicket-validation-bean library's.

(Igor)>this is probably a misuse of the compound property model, which is
evil anyways. you have to create your components with ids that match
the path from the root object, so if you want to access person.address
property you cant put a text field with id "address" into a
webmarkupcontainer of id "person", you have to add a text field with
component id "person.address"

I'm sorry that I can't send or post the problematic code; much of it is proprietary. Here's a censored précis.

I have a Report object for people to fill out. Report has a variable of type Publication, Publication being an interface.

public class Report implements Serializable {
	@Valid
	private Publication publication;
}

public interface Publication extends Serializable {}

public class Book implements Publication {}
public class Article implements Publication {}
public class Monograph implements Publication()

I have UI panels:

public class BookPanel extends FormComponentPanel<Book> {}
public class ArticlePanel extends FormComponentPanel<Article> {}
public class MonographPanel extends FormComponentPanel<Monograph> {}

I'm trying to create a PublicationPanel:

public class PublicationPanel extends FormComponentPanel<Publication> {
	private RadioChoice<String> publicationTypeChoice;
	private FormComponentPanel<? extends Publication> specificPublicationPanel;
}

I will swap a BookPanel, ArticlePanel, and MonographPanel in depending on the user's choice of type. If CompoundPropertyModels are evil (and I'd like a pointer to why), how can I take a IModel<Report> and turn it into a IModel<Publication> and IModel<Book>, and so on?  Does the metagen project handle the polymorphism?

Should I be using the single-argument constructor of FormComponentPanel<T> at all? Does it matter if I need to use the PublicationPanel more than once in the ReportForm?

Respectfully,
Eric Jablow

This communication, along with any attachments, is covered by federal and state law governing electronic communications and may contain company proprietary and legally privileged information.  If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution, use or copying of this message is strictly prohibited.  If you have received this in error, please reply immediately to the sender and delete this message.  Thank you.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: ValidationForm.addPropertyValidators sometimes looks for child properties in parent's model

Posted by Igor Vaynberg <ig...@gmail.com>.
inline,

On Thu, Nov 17, 2011 at 4:05 PM, Jablow, Eric R <Er...@mantech.com> wrote:
> I have some model classes with JSR 303 validation annotations, and I have some FormComponentPanels for each. Some of these will be nested. To test that the Wicket validation is correct, I'm creating a ValidationForm, which contains one of my panels, which contains another of my panels, and I am tying my form to a local minimal test object without the other fields I will be using later. I am using a CompoundPropertyModel. When I have the WicketTester initialize the ValidationForm, it looks for the 'parent' field in the minimal test object, which does exist.  Then, I get at line 302 of AbstractPropertyModel,
>
>      return PropertyResolver.getPropertyGetter(expression, target);
>
> I get a call with expression being "child", and target being the local test object.  Were expression "parent.child", this would succeed, as it would call getParent().getChild(). However, I'm not sure whether this is my bug or the wicket-validation-bean library's.

this is probably a misuse of the compound property model, which is
evil anyways. you have to create your components with ids that match
the path from the root object, so if you want to access person.address
property you cant put a text field with id "address" into a
webmarkupcontainer of id "person", you have to add a text field with
component id "person.address"

>
> Incidentally, I'm getting an interesting misfeature from the validation; the order in which the validations are > performed seems to be nondeterministic.

i dont think the spec defines order


> This means that the test below fails sometimes.
>
>                tester.assertFeedback("path:to:panel", new String[] {messageA, messageB});
>
> Often, when I reverse the order of messageA and messageB, the next test fails too! Perhaps Wicket 1.5.3 can have WicketTester.assertFeedback(String path, Set<String> messages).

maybe you can attach a patch to our jira

> Finally, I might need to avoid FormComponentPanels in the future, as some of the inner ones will be swapped in and out of the page depending on the user's choices.  I realize that the only panels that will be instrumented are the ones in the Form when it is originally configured.

thats not the case. components under the validationform are
instrumented before every render so its safe to swap things in and
out.

-igor


>
> Thanks in advance.
>
> Respectfully,
> Eric Jablow
>
> This communication, along with any attachments, is covered by federal and state law governing electronic communications and may contain company proprietary and legally privileged information.  If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution, use or copying of this message is strictly prohibited.  If you have received this in error, please reply immediately to the sender and delete this message.  Thank you.
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org