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 <s...@meiers.net> 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 <s...@meiers.net> 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 <mgrigo...@apache.org

wrote:

   On Fri, May 31, 2013 at 4:24 PM, tetsuo <ronald.tet...@gmail.com>
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 <
igor.vaynb...@gmail.com

  wrote:
On Thu, May 30, 2013 at 12:37 PM, tetsuo <ronald.tet...@gmail.com>

  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>>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 <

  mgrigo...@apache.org
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>>(Add
generics

  to
   o.a.w.Component)
2.

   
https://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/**
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