I made the changes to make it work, added a test case, and sent a pull
request on github.
Now it works when you create an unbound model from a class, and then bind
it to a plain model.


On Thu, Jun 13, 2013 at 6:39 PM, tetsuo <[email protected]> wrote:

> Well, you were the one who said that if I created the unbound model
> (from(A.class)) then I could bind it to a plain IModel, without the extra
> type information :)
>
> I just assumed that it would keep the 'A.class' information passed in the
> beginning and use it at runtime.
>
> It seems that the Evaluation holds the initial 'from' type, but it isn't
> passed down to LazyModel when it is created (it only receives target and
> stack), so it has to try to discover the type by itself, and fails.
>
> I'll try to do some experiments here...
>
>
>
>
>
> On Thu, Jun 13, 2013 at 6:21 PM, Sven Meier <[email protected]> wrote:
>
>> Well, here again LazyModel needs the type of the bound target at runtime.
>> Without any runtime information about the model's object type, LazyModel
>> cannot derive the type of the evaluation result.
>>
>> Sven
>>
>>
>> On 06/13/2013 10:55 PM, tetsuo wrote:
>>
>>> this test also passes here, but
>>>
>>>          assertEquals(B.class, ((IObjectClassAwareModel<B>)
>>> model.bind(a)).getObjectClass(**));
>>>
>>>          assertEquals(B.class, ((IObjectClassAwareModel<B>)
>>> model.bind(Model.of(a))).**getObjectClass());
>>>
>>>
>>> While the first assert passes, but the second one doesn't.
>>>
>>> The exception is thrown not when getting the object, but the object class
>>> (the AbstractTextComponent class calls this before rendering and while
>>> converting input).
>>>
>>>
>>>
>>>
>>>
>>> On Thu, Jun 13, 2013 at 5:40 PM, Sven Meier <[email protected]> wrote:
>>>
>>>  Strange, works fine here:
>>>>
>>>>      @Test
>>>>      public void bindToModelAndGet() {
>>>>          LazyModel<B> model = model(from(A.class).getB());
>>>>
>>>>          final A a = new A();
>>>>          a.b = new B();
>>>>
>>>>          assertEquals(a.b, model.bind(Model.of(a)).****getObject());
>>>>
>>>>      }
>>>>
>>>> Sven
>>>>
>>>>
>>>> On 06/13/2013 10:23 PM, tetsuo wrote:
>>>>
>>>>  Thanks for the response!
>>>>>
>>>>> If I use an object instance, it works, but if I do as your third
>>>>> example
>>>>> (create a model from the class, then bind to a
>>>>> non-IObjectClassAwareModel-****model),
>>>>>
>>>>> it doesn't:
>>>>>
>>>>> public class TestPage extends WebPage {
>>>>>
>>>>>       private String text;
>>>>>
>>>>>       public TestPage(final PageParameters parameters) {
>>>>>
>>>>>           super(parameters);
>>>>>
>>>>>           add(new Form<Void>("form")
>>>>>
>>>>>               .add(new TextField<String>("text",
>>>>> model(from(TestPage.class
>>>>> ).getText()).bind(Model.of(****this)))));
>>>>>
>>>>>
>>>>>       }
>>>>>
>>>>>       public String getText() { return text; }
>>>>>
>>>>>       public void setText(String text) { this.text = text; }
>>>>>
>>>>> }
>>>>>
>>>>>
>>>>> If I change 'Model.of(this)' to 'this' or an IObjectClassAwareModel
>>>>> implementation, it works:
>>>>>
>>>>>
>>>>>       class TestPageModel extends AbstractReadOnlyModel<****TestPage>
>>>>>
>>>>>           implements IObjectClassAwareModel<****TestPage> {
>>>>>
>>>>>
>>>>>           public TestPage getObject() { return TestPage.this; }
>>>>>
>>>>>           public Class<TestPage> getObjectClass() { return
>>>>> TestPage.class;
>>>>> }
>>>>>
>>>>>       }
>>>>>
>>>>>
>>>>> Is this a bug? I could create some wrapper models to make it work, but
>>>>> if
>>>>> this is a bug, I'd prefer to wait for a corrected version.
>>>>>
>>>>>
>>>>> Thanks again
>>>>>
>>>>>
>>>>> On Thu, Jun 13, 2013 at 4:52 PM, Sven Meier <[email protected]> wrote:
>>>>>
>>>>>   Hi,
>>>>>
>>>>>> LazyModel needs to know the type of the model object to return an
>>>>>> appropriate proxy:
>>>>>>
>>>>>>     model(from(a).getB()); // works
>>>>>>     model(from(aModel).getB()); // aModel must be an
>>>>>> IObjectClassAwareModel
>>>>>>     model(from(A.class).getB()).******bind(aModel); // works even if
>>>>>> aModel
>>>>>>
>>>>>>
>>>>>> does not reveal its object class
>>>>>>
>>>>>> Sven
>>>>>>
>>>>>>
>>>>>> On 06/13/2013 09:35 PM, tetsuo wrote:
>>>>>>
>>>>>>   wait, wait, do you actually do something like
>>>>>>
>>>>>>> new TextField<String>("name", new IModel<String>(){
>>>>>>>        public String getObject() {
>>>>>>>            return entity.getName();
>>>>>>>        }
>>>>>>>        public void setObject(String value) {
>>>>>>>            entity.setName(value);
>>>>>>>        }
>>>>>>>        public void detach(){}
>>>>>>> });
>>>>>>>
>>>>>>> for every single field in your system, or you use LazyModel?
>>>>>>>
>>>>>>> Well, I've been trying to use LazyModel, but with it I have to pass
>>>>>>> the
>>>>>>> type of every field (the last arg of TextField's constructor) because
>>>>>>> if I
>>>>>>> don't, this exception is thrown:
>>>>>>>
>>>>>>> Caused by: java.lang.******IllegalArgumentException: T is not a
>>>>>>> class or
>>>>>>> parameterizedType
>>>>>>>
>>>>>>> at org.wicketstuff.lazymodel.******reflect.Generics.getClass(**
>>>>>>> Generics.java:78)
>>>>>>>
>>>>>>> at org.wicketstuff.lazymodel.******LazyModel.getObjectType(**
>>>>>>> LazyModel.java:139)
>>>>>>>
>>>>>>> at org.wicketstuff.lazymodel.******LazyModel.getObjectClass(**
>>>>>>> LazyModel.java:124)
>>>>>>>
>>>>>>> at org.apache.wicket.markup.html.******form.**
>>>>>>> AbstractTextComponent.****
>>>>>>> getModelType(
>>>>>>> AbstractTextComponent.java:******167)
>>>>>>>
>>>>>>> at org.apache.wicket.markup.html.******form.**
>>>>>>> AbstractTextComponent.****
>>>>>>> resolveType(
>>>>>>> AbstractTextComponent.java:******152)
>>>>>>>
>>>>>>> at org.apache.wicket.markup.html.******form.**
>>>>>>> AbstractTextComponent.****
>>>>>>> onBeforeRender(
>>>>>>> AbstractTextComponent.java:******142)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Any thoughts?
>>>>>>>
>>>>>>> I guess I'll just go back to CompoundPropertyModel... (sigh)
>>>>>>>
>>>>>>>
>>>>>>> (and no, I don't spend that much time debugging property models. I
>>>>>>> usually
>>>>>>> don't rename properties that often, and when I have to do some
>>>>>>> refactoring,
>>>>>>> usually the structure changes, and I have to revise all pages
>>>>>>> anyway...)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Fri, May 31, 2013 at 10:49 AM, Martin Grigorov <
>>>>>>> [email protected]
>>>>>>>
>>>>>>>  wrote:
>>>>>>>>
>>>>>>>>     On Fri, May 31, 2013 at 4:24 PM, tetsuo <
>>>>>>> [email protected]>
>>>>>>> wrote:
>>>>>>>
>>>>>>>     Black magic, or code generation? hard choice... :)
>>>>>>>>
>>>>>>>>  I think I'll try the black magic, let's see how it goes :)
>>>>>>>>>
>>>>>>>>>    I personally prefer writing the boilerplate of custom Model per
>>>>>>>>> field.
>>>>>>>>>
>>>>>>>>>  It is a boring work but it gives me:
>>>>>>>> * type safety
>>>>>>>> * the fastest read/write access possible
>>>>>>>> * easier debugging
>>>>>>>>
>>>>>>>> (who knows - maybe I've spent less time to write such models than
>>>>>>>> you've
>>>>>>>> spent to debug your issues with property model after refactoring)
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>   On Thu, May 30, 2013 at 8:16 PM, Igor Vaynberg <
>>>>>>>>
>>>>>>>>> [email protected]
>>>>>>>>>
>>>>>>>>>   wrote:
>>>>>>>>>
>>>>>>>>>> On Thu, May 30, 2013 at 12:37 PM, tetsuo <[email protected]
>>>>>>>>>> >
>>>>>>>>>>
>>>>>>>>>>   wrote:
>>>>>>>>>>
>>>>>>>>>   -1000!
>>>>>>>>>
>>>>>>>>>> This will be horrible! Even with the current API, most generics I
>>>>>>>>>>>
>>>>>>>>>>>   have
>>>>>>>>>>>
>>>>>>>>>> to
>>>>>>>>>
>>>>>>>>>   declare in my code don't add anything to type safety. For
>>>>>>>>> example:
>>>>>>>>>
>>>>>>>>>> while i am also not a fan of having component generified i do
>>>>>>>>>> believe
>>>>>>>>>> the example below is a bit contrived.
>>>>>>>>>>
>>>>>>>>>> first, i hope most people do not use PropertyModels because they
>>>>>>>>>> are
>>>>>>>>>> not compile-time-safe. there are plenty of project that implement
>>>>>>>>>> compile-time-safe models, personally i prefer
>>>>>>>>>> https://github.com/42Lines/******metagen<https://github.com/42Lines/****metagen>
>>>>>>>>>> <https://github.com/**42Lines/**metagen<https://github.com/42Lines/**metagen>
>>>>>>>>>> >
>>>>>>>>>> <https://github.com/**42Lines/**metagen<https://github.com/**42Lines/metagen>
>>>>>>>>>> <https://github.com/**42Lines/metagen<https://github.com/42Lines/metagen>
>>>>>>>>>> >>to
>>>>>>>>>>
>>>>>>>>>> using proxy-based solutions.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> further, i hope even less people use compound property models.
>>>>>>>>>> they
>>>>>>>>>> are even more unsafe then property models and make your code even
>>>>>>>>>> more
>>>>>>>>>> fragile. i would hate to refactor code that uses CPMs.
>>>>>>>>>>
>>>>>>>>>>        add(new Form<Person>("form", new
>>>>>>>>>> CompoundPropertyModel<Person>(
>>>>>>>>>> ****
>>>>>>>>>>
>>>>>>>>>>   new
>>>>>>>>>>
>>>>>>>>>>> PropertyModel<Person>(this, "person")))
>>>>>>>>>>>          .add(new TextField<String>("name"))
>>>>>>>>>>>          .add(new TextField<Integer>("age"))
>>>>>>>>>>>          .add(new TextField<Double>("salary"))
>>>>>>>>>>>          .add(new Button("save", new
>>>>>>>>>>>
>>>>>>>>>>>   PropertyModel<Person>(this,"******person")){
>>>>>>>>>>>
>>>>>>>>>>             public void onSubmit() {
>>>>>>>>>>
>>>>>>>>>>     repository.save((Person)******getForm().****
>>>>>>>>>>> getDefaultModelObject());
>>>>>>>>>>>
>>>>>>>>>>>              }
>>>>>>>>>>          });
>>>>>>>>>>
>>>>>>>>>>> In my experience, this kind of code is fairly common in Wicket
>>>>>>>>>>> applications. Every form component must be declared with a type,
>>>>>>>>>>> but
>>>>>>>>>>>
>>>>>>>>>>>   none
>>>>>>>>>>>
>>>>>>>>>> has *any* kind of type safety gain.
>>>>>>>>>> but how often do you declare a form component without adding any
>>>>>>>>>> validators to it? the generic type of component also makes sure
>>>>>>>>>> you
>>>>>>>>>> add the correct validator. for example it wont let you add a
>>>>>>>>>> validator
>>>>>>>>>> that expects strings to a component that produces integers.
>>>>>>>>>>
>>>>>>>>>> also, not sure why you are replicating the model in Button. first,
>>>>>>>>>> the
>>>>>>>>>> Button uses its model to fill its label; secondly, in real code
>>>>>>>>>> the
>>>>>>>>>> model would be in a final var or field that things like onsubmit
>>>>>>>>>> can
>>>>>>>>>> access easily.
>>>>>>>>>>
>>>>>>>>>> -igor
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>    - The property model uses reflection, so its type can't be
>>>>>>>>>> verified
>>>>>>>>>> by
>>>>>>>>>>
>>>>>>>>>>  the
>>>>>>>>>
>>>>>>>>>  compiler (this.person could be anything, not just a Person).
>>>>>>>>>>
>>>>>>>>>>> - Generics will guarantee that the form model will be of type
>>>>>>>>>>> Person,
>>>>>>>>>>>
>>>>>>>>>>>   but
>>>>>>>>>>>
>>>>>>>>>> since it's all declared inline, and the real model isn't
>>>>>>>>>> verifiable,
>>>>>>>>>> it
>>>>>>>>>>
>>>>>>>>>>  just adds lots of verbosity without any real gain.
>>>>>>>>>
>>>>>>>>>  - Most form components use the implicit model, that also uses
>>>>>>>>>>
>>>>>>>>>>>   reflection,
>>>>>>>>>>>
>>>>>>>>>> and also can't verify the actual type of the underlying property,
>>>>>>>>>> at
>>>>>>>>>>
>>>>>>>>>>  compilation time. Even in runtime, *the type information is lost
>>>>>>>>>>> due
>>>>>>>>>>>
>>>>>>>>>>>   erasure
>>>>>>>>>>>
>>>>>>>>>>   *, so it can't use it to do any additional verification.
>>>>>>>>>>
>>>>>>>>>>> *- Worse, you can even declare the "name" TextField as <Integer>
>>>>>>>>>>> or
>>>>>>>>>>> <Double> (while maintaining the 'text' attribute as String), and
>>>>>>>>>>>
>>>>>>>>>>>   since
>>>>>>>>>>>
>>>>>>>>>> there is no type information at runtime, it doesn't matter. It
>>>>>>>>> won't
>>>>>>>>>
>>>>>>>>>  even
>>>>>>>>>> throw an exception (it will just work normally).* In this case,
>>>>>>>>>> the
>>>>>>>>>> type
>>>>>>>>>> declaration is simply a lie.
>>>>>>>>>>
>>>>>>>>>>  Just pain, no gain. In my code, I sometimes just add a
>>>>>>>>>>>
>>>>>>>>>>>   @SuppressWarnings(
>>>>>>>>>>>
>>>>>>>>>> "rawtypes") to the class, and remove all useless generic type
>>>>>>>>>> declarations.
>>>>>>>>>>
>>>>>>>>>>   If everything will be required to declare them, I will have do
>>>>>>>>>> it
>>>>>>>>>>
>>>>>>>>>>>   more
>>>>>>>>>>>
>>>>>>>>>> frequently.
>>>>>>>>>
>>>>>>>>>  That said, repeater components benefit greatly from generics. So
>>>>>>>>>> do
>>>>>>>>>>
>>>>>>>>>>>   custom
>>>>>>>>>>>
>>>>>>>>>>   models, validators, and converters. Or the rare cases that we
>>>>>>>>>>
>>>>>>>>>>>   explicitly
>>>>>>>>>>>
>>>>>>>>>> declare the form component model. But forcing everything to be
>>>>>>>>>>
>>>>>>>>>>  generic-typed will just make Wicket extremely verbose to use,
>>>>>>>>>>> with
>>>>>>>>>>>
>>>>>>>>>>>   very
>>>>>>>>>>>
>>>>>>>>>> little benefit.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>> On Thu, May 30, 2013 at 4:00 AM, Martin Grigorov <
>>>>>>>>>>>
>>>>>>>>>>>   [email protected]
>>>>>>>>>>>
>>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>     Hi,
>>>>>>>>>>
>>>>>>>>>>> I just pushed some initial work for [1] and [2] in
>>>>>>>>>>>> branch generified-component-4930.
>>>>>>>>>>>>
>>>>>>>>>>>> So far it doesn't look nice.
>>>>>>>>>>>>
>>>>>>>>>>>> The added generics break somehow setMetaData/getMetaData
>>>>>>>>>>>> methods -
>>>>>>>>>>>>
>>>>>>>>>>>>   you
>>>>>>>>>>>>
>>>>>>>>>>> can
>>>>>>>>>> see compilation errors in Component and Page classes. I think it
>>>>>>>>>> is
>>>>>>>>>>
>>>>>>>>>>> caused
>>>>>>>>>>> by the anonymous instance of MetaDataKey ( new
>>>>>>>>>>> MetaDataKey<T>(type)
>>>>>>>>>>> {}
>>>>>>>>>>>
>>>>>>>>>>>  ).
>>>>>>>>>> Also the visit*** methods do not compile at the moment, but even
>>>>>>>>>> if
>>>>>>>>>>
>>>>>>>>>>> we
>>>>>>>>>>>
>>>>>>>>>>>  find
>>>>>>>>>> a way to fix their signature I think writing a visitor will become
>>>>>>>>>>
>>>>>>>>>>> quite
>>>>>>>>>>>
>>>>>>>>>>>  cumbersome.
>>>>>>>>>>
>>>>>>>>>>    At the moment we have IVisitor
>>>>>>>>>>>
>>>>>>>>>>>> and org.apache.wicket.util.******iterator.****
>>>>>>>>>>>> AbstractHierarchyIterator
>>>>>>>>>>>> which
>>>>>>>>>>>>
>>>>>>>>>>>>   do
>>>>>>>>>>>>
>>>>>>>>>>> the
>>>>>>>>>> same job. The Iterator API is supposed to be simpler to write for
>>>>>>>>>>
>>>>>>>>>>> the
>>>>>>>>>>>
>>>>>>>>>>>     users. Maybe we can drop  IVisitor ... ?!
>>>>>>>>>>   I'd like to ask for help with this task. It is supposed to be
>>>>>>>>>> the
>>>>>>>>>>
>>>>>>>>>>>   biggest
>>>>>>>>>>>>
>>>>>>>>>>> API break for Wicket 7.0. My current feeling is that the end
>>>>>>>>>>> result
>>>>>>>>>>> won't
>>>>>>>>>>> be very pleasant for the user-land code.
>>>>>>>>>>>
>>>>>>>>>>>  For example the application code will have to do something like:
>>>>>>>>>>>>
>>>>>>>>>>>>      WebMarkupContainer<Void> wmc = new
>>>>>>>>>>>> WebMarkupContainer<>("id")
>>>>>>>>>>>>
>>>>>>>>>>>> It is not that much but we have to decide whether we want it.
>>>>>>>>>>>> But first let's try to fix the compilation problems.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> 1. 
>>>>>>>>>>>> https://issues.apache.org/******jira/browse/WICKET-4930<https://issues.apache.org/****jira/browse/WICKET-4930>
>>>>>>>>>>>> <https:**//issues.apache.org/**jira/**browse/WICKET-4930<https://issues.apache.org/**jira/browse/WICKET-4930>
>>>>>>>>>>>> >
>>>>>>>>>>>> <https:**//issues.apache.org/**jira/**browse/WICKET-4930<http://issues.apache.org/jira/**browse/WICKET-4930>
>>>>>>>>>>>> <http**s://issues.apache.org/jira/**browse/WICKET-4930<https://issues.apache.org/jira/browse/WICKET-4930>
>>>>>>>>>>>> >>(Add
>>>>>>>>>>>> generics
>>>>>>>>>>>>
>>>>>>>>>>>>   to
>>>>>>>>>>>>
>>>>>>>>>>>    o.a.w.Component)
>>>>>>>>>> 2.
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>    
>>>>>>>>>>>> https://cwiki.apache.org/******confluence/display/WICKET/**<https://cwiki.apache.org/****confluence/display/WICKET/**>
>>>>>>>>>>>> <h**ttps://cwiki.apache.org/****confluence/display/WICKET/**<https://cwiki.apache.org/**confluence/display/WICKET/**>
>>>>>>>>>>>> >
>>>>>>>>>>>>
>>>>>>>>>>>>  Wicket+7.0+Roadmap#Wicket7.******0Roadmap-Genericsfororg.**
>>>>>>>>>>>
>>>>>>>>>> apache.wicket.Component<https:****//cwiki.apache.org/**
>>>>>>>> confluence/** <http://cwiki.apache.org/confluence/**>
>>>>>>>> display/WICKET/Wicket+7.0+****Roadmap#Wicket7.0Roadmap-**
>>>>>>>> Genericsfororg.apache.wicket.****Component<https://cwiki.**
>>>>>>>> apache.org/confluence/display/**WICKET/Wicket+7.0+Roadmap#**
>>>>>>>> Wicket7.0Roadmap-**Genericsfororg.apache.wicket.**Component<https://cwiki.apache.org/confluence/display/WICKET/Wicket+7.0+Roadmap#Wicket7.0Roadmap-Genericsfororg.apache.wicket.Component>
>>>>>>>> >
>>>>>>>>
>>>>>>>>
>>
>

Reply via email to