You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wicket.apache.org by Martijn Dashorst <ma...@gmail.com> on 2016/11/10 11:56:50 UTC

LambdaModel for readonly models

I'm working on replacing my AROM's and often they just call a getter.
In that case I'd rather use a method reference than doing the IModel
replacement.

Is there a reason why the LambdaModel doesn't have a path for only a getter?

This way I can do:

public A(String p, final SerializableSupplier<Boolean> visibility)
{
    this(p);
    condition = LambdaModel.of(visibility);
}

instead of:

public A(String p, final SerializableSupplier<Boolean> visibility)
{
    this(p);
    condition = new IModel<Boolean>() {
        private static final long serialVersionUID = 1L;

        @Override
        public Boolean getObject() {
            return visibility.get();
        }
    };
}

I have the code ready to push, shall I?

Martijn

Re: LambdaModel for readonly models

Posted by Matthias Metzger <no...@yahoo.de.INVALID>.
Sorry, forgot:

Best regards of course :)

Matthias

On 10.11.2016 22:03, Matthias Metzger wrote:
> Though it probably does not matter, I just wanted to add, that the
> chained lambda does null checks for the contained object for every #map
> call in the chain. Except for the property model, neither of the others
> does that - at least, as far as I could see.
> 
> So the following, quickly hacked together solution should be equivalent
> to chained #map calls.
> 
> if (accountModel.getObject() != null &&
> accountModel.getObject().getPerson() != null &&
> accountModel.getObject().getPerson().getName() != null)
> {
>   return accountModel.getObject().getPerson().getName();
> }
> else
> {
>   return null;
> }
> 
> On 10.11.2016 21:01, Martijn Dashorst wrote:
>> I just did a micro benchmark to see which is faster.
>>
>> The project is here:
>>
>> https://github.com/dashorst/wicket-benchmarks
>>
>> You can see the test code here:
>>
>> https://github.com/dashorst/wicket-benchmarks/blob/master/src/main/java/com/martijndashorst/wicketbenchmarks/LambdaModels.java
>>
>> The results are (on my laptop) for this particular run (10 warmup
>> rounds for each iteration of 1s, each benchmark consists of 10
>> iterations of 10 seconds each):
>>
>> LambdaModels.nativeEvaluation       thrpt   10  357854132.948 �
>> 5459963.153  ops/s
>> LambdaModels.abstractReadOnlyModel  thrpt   10  261693660.899 �
>> 2008898.403  ops/s
>> LambdaModels.directLambdaModel      thrpt   10  216231074.508 �
>> 3866874.908  ops/s
>> LambdaModels.chainedLambdaModel     thrpt   10  152373429.346 �
>> 938206.534  ops/s
>> LambdaModels.propertyModel          thrpt   10    2180390.984 �
>> 72875.218  ops/s
>>
>> In other words:
>>
>> if property model has performance of 1, a chained lamda has a better
>> performance of 70x that. The direct lambda model has a performance of
>> 99x a property model, retrieving a property value directly using a
>> abstract read only model is 120x more performant than a property
>> model. And just directly getting the value of the property without
>> wrapping it in a model is 164x faster than using a property model.
>>
>> Will this matter? Probably a little bit for your overall application
>> if it is heavily used. If you have a page with lots of property models
>> you can do a lot better by using lambda models if you need the
>> dynamism.
>>
>> Martijn
>>
>>
>> On Thu, Nov 10, 2016 at 1:38 PM, Martijn Dashorst
>> <ma...@gmail.com> wrote:
>>> IModel<String> m =
>>>   LoadableDetachableModel
>>>     .of(Person::new)
>>>     .map(Person::getName);
>>>
>>> So much sexiness with lambda's and models...
>>>
>>> IModel<Account> a = ...;
>>> IModel<Person> p = a.map(Account::getPerson);
>>>
>>> add(new Label("firstName", p.map(Person::getFirstName));
>>> add(new Label("lastName", p.map(Person::getLastName));
>>>
>>> Too bad Java doesn't have properties as a language construct. That
>>> would make this even better:
>>>
>>> IModel<Account> a = ...;
>>> IModel<Person> p = a.map(Account::person);
>>>
>>> add(new Label("firstName", p.map(Person::firstName));
>>> add(new Label("lastName", p.map(Person::lastName));
>>>
>>> Martijn
>>>
>>> On Thu, Nov 10, 2016 at 1:17 PM, Martin Grigorov <mg...@apache.org> wrote:
>>>>  grep Label | grep '::' wicket-examples/src/main/java/
>>>> wicket-examples/src/main/java/org/apache/wicket/examples/
>>>> ajax/builtin/FileUploadPage.java
>>>> 87: form.add(new Label("max", form::getMaxSize));
>>>>
>>>> wicket-examples/src/main/java/org/apache/wicket/examples/
>>>> ajax/builtin/GuestBook.java
>>>> 78: listItem.add(new Label("date", comment::getDate));
>>>>
>>>> wicket-examples/src/main/java/org/apache/wicket/examples/
>>>> compref/LabelPage.java
>>>> 45: add(new Label("dynamicLabel", Date::new));
>>>>
>>>> wicket-examples/src/main/java/org/apache/wicket/examples/
>>>> compref/LinkPage.java
>>>> 48: link1.add(new Label("label1", count1::toString));
>>>>
>>>>
>>>> Martin Grigorov
>>>> Wicket Training and Consulting
>>>> https://twitter.com/mtgrigorov
>>>>
>>>> On Thu, Nov 10, 2016 at 1:05 PM, Emond Papegaaij <emond.papegaaij@topicus.nl
>>>>> wrote:
>>>>
>>>>> Didn't we make IModel a functional interface with default methods for
>>>>> setObject and detach? In that case, you can simply use a method reference
>>>>> as
>>>>> your model.
>>>>>
>>>>> Emond
>>>>>
>>>>> On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
>>>>>> I'm working on replacing my AROM's and often they just call a getter.
>>>>>> In that case I'd rather use a method reference than doing the IModel
>>>>>> replacement.
>>>>>>
>>>>>> Is there a reason why the LambdaModel doesn't have a path for only a
>>>>> getter?
>>>>>>
>>>>>> This way I can do:
>>>>>>
>>>>>> public A(String p, final SerializableSupplier<Boolean> visibility)
>>>>>> {
>>>>>>     this(p);
>>>>>>     condition = LambdaModel.of(visibility);
>>>>>> }
>>>>>>
>>>>>> instead of:
>>>>>>
>>>>>> public A(String p, final SerializableSupplier<Boolean> visibility)
>>>>>> {
>>>>>>     this(p);
>>>>>>     condition = new IModel<Boolean>() {
>>>>>>         private static final long serialVersionUID = 1L;
>>>>>>
>>>>>>         @Override
>>>>>>         public Boolean getObject() {
>>>>>>             return visibility.get();
>>>>>>         }
>>>>>>     };
>>>>>> }
>>>>>>
>>>>>> I have the code ready to push, shall I?
>>>>>>
>>>>>> Martijn
>>>>>
>>>>>
>>>>>
>>>
>>>
>>>
>>> --
>>> Become a Wicket expert, learn from the best: http://wicketinaction.com
>>
>>
>>

Re: LambdaModel for readonly models

Posted by Martijn Dashorst <ma...@gmail.com>.
On Thu, Nov 10, 2016 at 10:03 PM, Matthias Metzger
<no...@yahoo.de.invalid> wrote:
> Though it probably does not matter, I just wanted to add, that the
> chained lambda does null checks for the contained object for every #map
> call in the chain. Except for the property model, neither of the others
> does that - at least, as far as I could see.

I've tested it, and adding additional cases for the if statements only
make the benchmark run longer for the added tests. In the grand
picture and even the small picture the null checks are negligible. A
method call costs an order more cycles according to these tests.

There's so much to love about micro benchmarks, mostly the discussions
that arise from them about micro details ;-)

:beers:

Martijn

Re: LambdaModel for readonly models

Posted by Matthias Metzger <no...@yahoo.de.INVALID>.
Though it probably does not matter, I just wanted to add, that the
chained lambda does null checks for the contained object for every #map
call in the chain. Except for the property model, neither of the others
does that - at least, as far as I could see.

So the following, quickly hacked together solution should be equivalent
to chained #map calls.

if (accountModel.getObject() != null &&
accountModel.getObject().getPerson() != null &&
accountModel.getObject().getPerson().getName() != null)
{
  return accountModel.getObject().getPerson().getName();
}
else
{
  return null;
}

On 10.11.2016 21:01, Martijn Dashorst wrote:
> I just did a micro benchmark to see which is faster.
> 
> The project is here:
> 
> https://github.com/dashorst/wicket-benchmarks
> 
> You can see the test code here:
> 
> https://github.com/dashorst/wicket-benchmarks/blob/master/src/main/java/com/martijndashorst/wicketbenchmarks/LambdaModels.java
> 
> The results are (on my laptop) for this particular run (10 warmup
> rounds for each iteration of 1s, each benchmark consists of 10
> iterations of 10 seconds each):
> 
> LambdaModels.nativeEvaluation       thrpt   10  357854132.948 �
> 5459963.153  ops/s
> LambdaModels.abstractReadOnlyModel  thrpt   10  261693660.899 �
> 2008898.403  ops/s
> LambdaModels.directLambdaModel      thrpt   10  216231074.508 �
> 3866874.908  ops/s
> LambdaModels.chainedLambdaModel     thrpt   10  152373429.346 �
> 938206.534  ops/s
> LambdaModels.propertyModel          thrpt   10    2180390.984 �
> 72875.218  ops/s
> 
> In other words:
> 
> if property model has performance of 1, a chained lamda has a better
> performance of 70x that. The direct lambda model has a performance of
> 99x a property model, retrieving a property value directly using a
> abstract read only model is 120x more performant than a property
> model. And just directly getting the value of the property without
> wrapping it in a model is 164x faster than using a property model.
> 
> Will this matter? Probably a little bit for your overall application
> if it is heavily used. If you have a page with lots of property models
> you can do a lot better by using lambda models if you need the
> dynamism.
> 
> Martijn
> 
> 
> On Thu, Nov 10, 2016 at 1:38 PM, Martijn Dashorst
> <ma...@gmail.com> wrote:
>> IModel<String> m =
>>   LoadableDetachableModel
>>     .of(Person::new)
>>     .map(Person::getName);
>>
>> So much sexiness with lambda's and models...
>>
>> IModel<Account> a = ...;
>> IModel<Person> p = a.map(Account::getPerson);
>>
>> add(new Label("firstName", p.map(Person::getFirstName));
>> add(new Label("lastName", p.map(Person::getLastName));
>>
>> Too bad Java doesn't have properties as a language construct. That
>> would make this even better:
>>
>> IModel<Account> a = ...;
>> IModel<Person> p = a.map(Account::person);
>>
>> add(new Label("firstName", p.map(Person::firstName));
>> add(new Label("lastName", p.map(Person::lastName));
>>
>> Martijn
>>
>> On Thu, Nov 10, 2016 at 1:17 PM, Martin Grigorov <mg...@apache.org> wrote:
>>>  grep Label | grep '::' wicket-examples/src/main/java/
>>> wicket-examples/src/main/java/org/apache/wicket/examples/
>>> ajax/builtin/FileUploadPage.java
>>> 87: form.add(new Label("max", form::getMaxSize));
>>>
>>> wicket-examples/src/main/java/org/apache/wicket/examples/
>>> ajax/builtin/GuestBook.java
>>> 78: listItem.add(new Label("date", comment::getDate));
>>>
>>> wicket-examples/src/main/java/org/apache/wicket/examples/
>>> compref/LabelPage.java
>>> 45: add(new Label("dynamicLabel", Date::new));
>>>
>>> wicket-examples/src/main/java/org/apache/wicket/examples/
>>> compref/LinkPage.java
>>> 48: link1.add(new Label("label1", count1::toString));
>>>
>>>
>>> Martin Grigorov
>>> Wicket Training and Consulting
>>> https://twitter.com/mtgrigorov
>>>
>>> On Thu, Nov 10, 2016 at 1:05 PM, Emond Papegaaij <emond.papegaaij@topicus.nl
>>>> wrote:
>>>
>>>> Didn't we make IModel a functional interface with default methods for
>>>> setObject and detach? In that case, you can simply use a method reference
>>>> as
>>>> your model.
>>>>
>>>> Emond
>>>>
>>>> On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
>>>>> I'm working on replacing my AROM's and often they just call a getter.
>>>>> In that case I'd rather use a method reference than doing the IModel
>>>>> replacement.
>>>>>
>>>>> Is there a reason why the LambdaModel doesn't have a path for only a
>>>> getter?
>>>>>
>>>>> This way I can do:
>>>>>
>>>>> public A(String p, final SerializableSupplier<Boolean> visibility)
>>>>> {
>>>>>     this(p);
>>>>>     condition = LambdaModel.of(visibility);
>>>>> }
>>>>>
>>>>> instead of:
>>>>>
>>>>> public A(String p, final SerializableSupplier<Boolean> visibility)
>>>>> {
>>>>>     this(p);
>>>>>     condition = new IModel<Boolean>() {
>>>>>         private static final long serialVersionUID = 1L;
>>>>>
>>>>>         @Override
>>>>>         public Boolean getObject() {
>>>>>             return visibility.get();
>>>>>         }
>>>>>     };
>>>>> }
>>>>>
>>>>> I have the code ready to push, shall I?
>>>>>
>>>>> Martijn
>>>>
>>>>
>>>>
>>
>>
>>
>> --
>> Become a Wicket expert, learn from the best: http://wicketinaction.com
> 
> 
> 

Re: LambdaModel for readonly models

Posted by Martijn Dashorst <ma...@gmail.com>.
I just did a micro benchmark to see which is faster.

The project is here:

https://github.com/dashorst/wicket-benchmarks

You can see the test code here:

https://github.com/dashorst/wicket-benchmarks/blob/master/src/main/java/com/martijndashorst/wicketbenchmarks/LambdaModels.java

The results are (on my laptop) for this particular run (10 warmup
rounds for each iteration of 1s, each benchmark consists of 10
iterations of 10 seconds each):

LambdaModels.nativeEvaluation       thrpt   10  357854132.948 ±
5459963.153  ops/s
LambdaModels.abstractReadOnlyModel  thrpt   10  261693660.899 ±
2008898.403  ops/s
LambdaModels.directLambdaModel      thrpt   10  216231074.508 ±
3866874.908  ops/s
LambdaModels.chainedLambdaModel     thrpt   10  152373429.346 ±
938206.534  ops/s
LambdaModels.propertyModel          thrpt   10    2180390.984 ±
72875.218  ops/s

In other words:

if property model has performance of 1, a chained lamda has a better
performance of 70x that. The direct lambda model has a performance of
99x a property model, retrieving a property value directly using a
abstract read only model is 120x more performant than a property
model. And just directly getting the value of the property without
wrapping it in a model is 164x faster than using a property model.

Will this matter? Probably a little bit for your overall application
if it is heavily used. If you have a page with lots of property models
you can do a lot better by using lambda models if you need the
dynamism.

Martijn


On Thu, Nov 10, 2016 at 1:38 PM, Martijn Dashorst
<ma...@gmail.com> wrote:
> IModel<String> m =
>   LoadableDetachableModel
>     .of(Person::new)
>     .map(Person::getName);
>
> So much sexiness with lambda's and models...
>
> IModel<Account> a = ...;
> IModel<Person> p = a.map(Account::getPerson);
>
> add(new Label("firstName", p.map(Person::getFirstName));
> add(new Label("lastName", p.map(Person::getLastName));
>
> Too bad Java doesn't have properties as a language construct. That
> would make this even better:
>
> IModel<Account> a = ...;
> IModel<Person> p = a.map(Account::person);
>
> add(new Label("firstName", p.map(Person::firstName));
> add(new Label("lastName", p.map(Person::lastName));
>
> Martijn
>
> On Thu, Nov 10, 2016 at 1:17 PM, Martin Grigorov <mg...@apache.org> wrote:
>>  grep Label | grep '::' wicket-examples/src/main/java/
>> wicket-examples/src/main/java/org/apache/wicket/examples/
>> ajax/builtin/FileUploadPage.java
>> 87: form.add(new Label("max", form::getMaxSize));
>>
>> wicket-examples/src/main/java/org/apache/wicket/examples/
>> ajax/builtin/GuestBook.java
>> 78: listItem.add(new Label("date", comment::getDate));
>>
>> wicket-examples/src/main/java/org/apache/wicket/examples/
>> compref/LabelPage.java
>> 45: add(new Label("dynamicLabel", Date::new));
>>
>> wicket-examples/src/main/java/org/apache/wicket/examples/
>> compref/LinkPage.java
>> 48: link1.add(new Label("label1", count1::toString));
>>
>>
>> Martin Grigorov
>> Wicket Training and Consulting
>> https://twitter.com/mtgrigorov
>>
>> On Thu, Nov 10, 2016 at 1:05 PM, Emond Papegaaij <emond.papegaaij@topicus.nl
>>> wrote:
>>
>>> Didn't we make IModel a functional interface with default methods for
>>> setObject and detach? In that case, you can simply use a method reference
>>> as
>>> your model.
>>>
>>> Emond
>>>
>>> On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
>>> > I'm working on replacing my AROM's and often they just call a getter.
>>> > In that case I'd rather use a method reference than doing the IModel
>>> > replacement.
>>> >
>>> > Is there a reason why the LambdaModel doesn't have a path for only a
>>> getter?
>>> >
>>> > This way I can do:
>>> >
>>> > public A(String p, final SerializableSupplier<Boolean> visibility)
>>> > {
>>> >     this(p);
>>> >     condition = LambdaModel.of(visibility);
>>> > }
>>> >
>>> > instead of:
>>> >
>>> > public A(String p, final SerializableSupplier<Boolean> visibility)
>>> > {
>>> >     this(p);
>>> >     condition = new IModel<Boolean>() {
>>> >         private static final long serialVersionUID = 1L;
>>> >
>>> >         @Override
>>> >         public Boolean getObject() {
>>> >             return visibility.get();
>>> >         }
>>> >     };
>>> > }
>>> >
>>> > I have the code ready to push, shall I?
>>> >
>>> > Martijn
>>>
>>>
>>>
>
>
>
> --
> Become a Wicket expert, learn from the best: http://wicketinaction.com



-- 
Become a Wicket expert, learn from the best: http://wicketinaction.com

Re: LambdaModel for readonly models

Posted by Martijn Dashorst <ma...@gmail.com>.
IModel<String> m =
  LoadableDetachableModel
    .of(Person::new)
    .map(Person::getName);

So much sexiness with lambda's and models...

IModel<Account> a = ...;
IModel<Person> p = a.map(Account::getPerson);

add(new Label("firstName", p.map(Person::getFirstName));
add(new Label("lastName", p.map(Person::getLastName));

Too bad Java doesn't have properties as a language construct. That
would make this even better:

IModel<Account> a = ...;
IModel<Person> p = a.map(Account::person);

add(new Label("firstName", p.map(Person::firstName));
add(new Label("lastName", p.map(Person::lastName));

Martijn

On Thu, Nov 10, 2016 at 1:17 PM, Martin Grigorov <mg...@apache.org> wrote:
>  grep Label | grep '::' wicket-examples/src/main/java/
> wicket-examples/src/main/java/org/apache/wicket/examples/
> ajax/builtin/FileUploadPage.java
> 87: form.add(new Label("max", form::getMaxSize));
>
> wicket-examples/src/main/java/org/apache/wicket/examples/
> ajax/builtin/GuestBook.java
> 78: listItem.add(new Label("date", comment::getDate));
>
> wicket-examples/src/main/java/org/apache/wicket/examples/
> compref/LabelPage.java
> 45: add(new Label("dynamicLabel", Date::new));
>
> wicket-examples/src/main/java/org/apache/wicket/examples/
> compref/LinkPage.java
> 48: link1.add(new Label("label1", count1::toString));
>
>
> Martin Grigorov
> Wicket Training and Consulting
> https://twitter.com/mtgrigorov
>
> On Thu, Nov 10, 2016 at 1:05 PM, Emond Papegaaij <emond.papegaaij@topicus.nl
>> wrote:
>
>> Didn't we make IModel a functional interface with default methods for
>> setObject and detach? In that case, you can simply use a method reference
>> as
>> your model.
>>
>> Emond
>>
>> On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
>> > I'm working on replacing my AROM's and often they just call a getter.
>> > In that case I'd rather use a method reference than doing the IModel
>> > replacement.
>> >
>> > Is there a reason why the LambdaModel doesn't have a path for only a
>> getter?
>> >
>> > This way I can do:
>> >
>> > public A(String p, final SerializableSupplier<Boolean> visibility)
>> > {
>> >     this(p);
>> >     condition = LambdaModel.of(visibility);
>> > }
>> >
>> > instead of:
>> >
>> > public A(String p, final SerializableSupplier<Boolean> visibility)
>> > {
>> >     this(p);
>> >     condition = new IModel<Boolean>() {
>> >         private static final long serialVersionUID = 1L;
>> >
>> >         @Override
>> >         public Boolean getObject() {
>> >             return visibility.get();
>> >         }
>> >     };
>> > }
>> >
>> > I have the code ready to push, shall I?
>> >
>> > Martijn
>>
>>
>>



-- 
Become a Wicket expert, learn from the best: http://wicketinaction.com

Re: LambdaModel for readonly models

Posted by Martin Grigorov <mg...@apache.org>.
 grep Label | grep '::' wicket-examples/src/main/java/
wicket-examples/src/main/java/org/apache/wicket/examples/
ajax/builtin/FileUploadPage.java
87: form.add(new Label("max", form::getMaxSize));

wicket-examples/src/main/java/org/apache/wicket/examples/
ajax/builtin/GuestBook.java
78: listItem.add(new Label("date", comment::getDate));

wicket-examples/src/main/java/org/apache/wicket/examples/
compref/LabelPage.java
45: add(new Label("dynamicLabel", Date::new));

wicket-examples/src/main/java/org/apache/wicket/examples/
compref/LinkPage.java
48: link1.add(new Label("label1", count1::toString));


Martin Grigorov
Wicket Training and Consulting
https://twitter.com/mtgrigorov

On Thu, Nov 10, 2016 at 1:05 PM, Emond Papegaaij <emond.papegaaij@topicus.nl
> wrote:

> Didn't we make IModel a functional interface with default methods for
> setObject and detach? In that case, you can simply use a method reference
> as
> your model.
>
> Emond
>
> On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
> > I'm working on replacing my AROM's and often they just call a getter.
> > In that case I'd rather use a method reference than doing the IModel
> > replacement.
> >
> > Is there a reason why the LambdaModel doesn't have a path for only a
> getter?
> >
> > This way I can do:
> >
> > public A(String p, final SerializableSupplier<Boolean> visibility)
> > {
> >     this(p);
> >     condition = LambdaModel.of(visibility);
> > }
> >
> > instead of:
> >
> > public A(String p, final SerializableSupplier<Boolean> visibility)
> > {
> >     this(p);
> >     condition = new IModel<Boolean>() {
> >         private static final long serialVersionUID = 1L;
> >
> >         @Override
> >         public Boolean getObject() {
> >             return visibility.get();
> >         }
> >     };
> > }
> >
> > I have the code ready to push, shall I?
> >
> > Martijn
>
>
>

Re: LambdaModel for readonly models

Posted by Sven Meier <sv...@meiers.net>.
Yes, that was the idea.

Sven


Am 10.11.2016 um 13:05 schrieb Emond Papegaaij:
> Didn't we make IModel a functional interface with default methods for
> setObject and detach? In that case, you can simply use a method reference as
> your model.
>
> Emond
>
> On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
>> I'm working on replacing my AROM's and often they just call a getter.
>> In that case I'd rather use a method reference than doing the IModel
>> replacement.
>>
>> Is there a reason why the LambdaModel doesn't have a path for only a getter?
>>
>> This way I can do:
>>
>> public A(String p, final SerializableSupplier<Boolean> visibility)
>> {
>>      this(p);
>>      condition = LambdaModel.of(visibility);
>> }
>>
>> instead of:
>>
>> public A(String p, final SerializableSupplier<Boolean> visibility)
>> {
>>      this(p);
>>      condition = new IModel<Boolean>() {
>>          private static final long serialVersionUID = 1L;
>>
>>          @Override
>>          public Boolean getObject() {
>>              return visibility.get();
>>          }
>>      };
>> }
>>
>> I have the code ready to push, shall I?
>>
>> Martijn
>


Re: LambdaModel for readonly models

Posted by Tobias Soloschenko <to...@googlemail.com>.
To make things shorter is ok - to hide information is not ok - later on it is hard to track what is going on.

Only my thoughts about the second code snippet

kind regards

Tobias

> Am 10.11.2016 um 13:18 schrieb Martijn Dashorst <ma...@gmail.com>:
> 
> That would transform the code from:
> 
> condition = new AbstractReadOnlyModel<Boolean>() {
>    public Boolean getObject() { return visibility.get(); }
> };
> 
> via:
> condition = LambdaModel.of(visibility);
> 
> to:
> condition = visibility::get;
> 
> Not sure if I like the latter, as it hides the model, making the code
> more obscure.
> 
> Martijn
> 
> 
> 
> On Thu, Nov 10, 2016 at 1:05 PM, Emond Papegaaij
> <em...@topicus.nl> wrote:
>> Didn't we make IModel a functional interface with default methods for
>> setObject and detach? In that case, you can simply use a method reference as
>> your model.
>> 
>> Emond
>> 
>>> On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
>>> I'm working on replacing my AROM's and often they just call a getter.
>>> In that case I'd rather use a method reference than doing the IModel
>>> replacement.
>>> 
>>> Is there a reason why the LambdaModel doesn't have a path for only a getter?
>>> 
>>> This way I can do:
>>> 
>>> public A(String p, final SerializableSupplier<Boolean> visibility)
>>> {
>>>    this(p);
>>>    condition = LambdaModel.of(visibility);
>>> }
>>> 
>>> instead of:
>>> 
>>> public A(String p, final SerializableSupplier<Boolean> visibility)
>>> {
>>>    this(p);
>>>    condition = new IModel<Boolean>() {
>>>        private static final long serialVersionUID = 1L;
>>> 
>>>        @Override
>>>        public Boolean getObject() {
>>>            return visibility.get();
>>>        }
>>>    };
>>> }
>>> 
>>> I have the code ready to push, shall I?
>>> 
>>> Martijn
>> 
>> 
> 
> 
> 
> -- 
> Become a Wicket expert, learn from the best: http://wicketinaction.com

Re: LambdaModel for readonly models

Posted by Martijn Dashorst <ma...@gmail.com>.
That would transform the code from:

condition = new AbstractReadOnlyModel<Boolean>() {
    public Boolean getObject() { return visibility.get(); }
};

via:
condition = LambdaModel.of(visibility);

to:
condition = visibility::get;

Not sure if I like the latter, as it hides the model, making the code
more obscure.

Martijn



On Thu, Nov 10, 2016 at 1:05 PM, Emond Papegaaij
<em...@topicus.nl> wrote:
> Didn't we make IModel a functional interface with default methods for
> setObject and detach? In that case, you can simply use a method reference as
> your model.
>
> Emond
>
> On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
>> I'm working on replacing my AROM's and often they just call a getter.
>> In that case I'd rather use a method reference than doing the IModel
>> replacement.
>>
>> Is there a reason why the LambdaModel doesn't have a path for only a getter?
>>
>> This way I can do:
>>
>> public A(String p, final SerializableSupplier<Boolean> visibility)
>> {
>>     this(p);
>>     condition = LambdaModel.of(visibility);
>> }
>>
>> instead of:
>>
>> public A(String p, final SerializableSupplier<Boolean> visibility)
>> {
>>     this(p);
>>     condition = new IModel<Boolean>() {
>>         private static final long serialVersionUID = 1L;
>>
>>         @Override
>>         public Boolean getObject() {
>>             return visibility.get();
>>         }
>>     };
>> }
>>
>> I have the code ready to push, shall I?
>>
>> Martijn
>
>



-- 
Become a Wicket expert, learn from the best: http://wicketinaction.com

Re: LambdaModel for readonly models

Posted by Emond Papegaaij <em...@topicus.nl>.
Didn't we make IModel a functional interface with default methods for 
setObject and detach? In that case, you can simply use a method reference as 
your model.

Emond

On donderdag 10 november 2016 12:56:50 CET Martijn Dashorst wrote:
> I'm working on replacing my AROM's and often they just call a getter.
> In that case I'd rather use a method reference than doing the IModel
> replacement.
> 
> Is there a reason why the LambdaModel doesn't have a path for only a getter?
> 
> This way I can do:
> 
> public A(String p, final SerializableSupplier<Boolean> visibility)
> {
>     this(p);
>     condition = LambdaModel.of(visibility);
> }
> 
> instead of:
> 
> public A(String p, final SerializableSupplier<Boolean> visibility)
> {
>     this(p);
>     condition = new IModel<Boolean>() {
>         private static final long serialVersionUID = 1L;
> 
>         @Override
>         public Boolean getObject() {
>             return visibility.get();
>         }
>     };
> }
> 
> I have the code ready to push, shall I?
> 
> Martijn



Re: LambdaModel for readonly models

Posted by Martijn Dashorst <ma...@gmail.com>.
I'll use Emond's suggestion in LambdaModel. My instinct says folks
will start looking there for inspiration of Java 8 lambda's and
models.

Martijn


On Fri, Nov 11, 2016 at 9:08 AM, Emond Papegaaij
<em...@topicus.nl> wrote:
> Can't this method be made like this (perhaps on IModel?):
>    /**
>     * Create a read-only {@link IModel}. Usage:
>     * <pre>
>     * {@code
>     *     LambdaModel.of(person::getName)
>     * }
>     * </pre>
>     * Note that {@link IModel} is a {@code FunctionalInterface} and you can
>     * also use a lambda directly as a model.
>     *
>     * @param getter used to get value
>     * @return model
>     *
>     * @param <T> model object type
>     */
>    public static <T> IModel<T> of(SerializableSupplier<T> getter)
>    {
>        return getter::get;
>    }
>
> Emond
>
>
> On donderdag 10 november 2016 21:40:58 CET Sven Meier wrote:
>> If Martijn needs this, I'd prefer just to add another factory method:
>>
>>      /**
>>       * Create a read-only {@link LambdaModel}. Usage:
>>       * <pre>
>>       * {@code
>>       *     LambdaModel.of(person::getName)
>>       * }
>>       * </pre>
>>       *
>>       * @param getter used to get value
>>       * @return model
>>       *
>>       * @param <T> model object type
>>       */
>>      public static <T> IModel<T> of(SerializableSupplier<T> getter)
>>      {
>>          return new LambdaModel<>(getter, (t) -> { throw new
>> UnsupportedOperationException(); });
>>      }
>>
>> And the setter should throw the exception.
>>
>> Have fun
>> Sven
>>
>> Am 10.11.2016 um 21:34 schrieb Martin Grigorov:
>> > I think there is no need of this change.
>> > But if others believe it's needed then #setObject should throw an
>> > exception
>> > as in IModel.
>> >
>> > On Nov 10, 2016 10:24 PM, "Martijn Dashorst" <ma...@gmail.com>
>> >
>> > wrote:
>> >> So are we pro/against expanding LambdaModel for support of a read only
>> >> variant?
>> >>
>> >> Reasons against:
>> >>   - not necessary with IModel as a functional interface
>> >>   - multiple ways to do things
>> >>
>> >> Reasons pro:
>> >>   - IModel version may not be as clear as a Lambda model
>> >>   - IModel version may not be as obvious a choice (years of experience
>> >>
>> >> with Java < 8 and Wicket < 8)
>> >>
>> >> Proposed patch:
>> >>
>> >> diff --git a/wicket-core/src/main/java/org/apache/wicket/model/
>> >> LambdaModel.java
>> >> b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>> >> index 8fb9d6a..ece4fe5 100644
>> >> --- a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>> >> +++ b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>> >> @@ -53,6 +53,19 @@ public class LambdaModel<T> implements IModel<T>
>> >>
>> >>    this.setter = Args.notNull(setter, "setter");
>> >>    }
>> >>
>> >> + /**
>> >> + * Construct the model, using the given supplier and consumer as
>> >> + * implementation for getObject and setObject.
>> >> + *
>> >> + * @param getter Used for the getObject() method.
>> >> + * @param setter Used for the setObject(T object) method.
>> >> + */
>> >> + public LambdaModel(SerializableSupplier<T> getter)
>> >> + {
>> >> + this.getter = Args.notNull(getter, "getter");
>> >> + this.setter = null;
>> >> + }
>> >> +
>> >>
>> >>    @Override
>> >>    public T getObject()
>> >>    {
>> >>
>> >> @@ -62,7 +75,8 @@ public class LambdaModel<T> implements IModel<T>
>> >>
>> >>    @Override
>> >>    public void setObject(T t)
>> >>    {
>> >>
>> >> - setter.accept(t);
>> >> + if(setter != null)
>> >> + setter.accept(t);
>> >>
>> >>    }
>> >>
>> >>    @Override
>> >>
>> >> @@ -114,6 +128,24 @@ public class LambdaModel<T> implements IModel<T>
>> >>
>> >>    }
>> >>
>> >>    /**
>> >>
>> >> + * Create a read only {@link LambdaModel}. Usage:
>> >> + * <pre>
>> >> + * {@code
>> >> + * LambdaModel.of(person::getName)
>> >> + * }
>> >> + * </pre>
>> >> + *
>> >> + * @param getter used to get value
>> >> + * @return model
>> >> + *
>> >> + * @param <T> model object type
>> >> + */
>> >> + public static <T> IModel<T> of(SerializableSupplier<T> getter)
>> >> + {
>> >> + return new LambdaModel<>(getter);
>> >> + }
>> >> +
>> >> + /**
>> >>
>> >>    * Create a {@link LambdaModel} for a given target. Usage:
>> >>    * <pre>
>> >>    * {@code
>
>



-- 
Become a Wicket expert, learn from the best: http://wicketinaction.com

Re: LambdaModel for readonly models

Posted by Emond Papegaaij <em...@topicus.nl>.
Can't this method be made like this (perhaps on IModel?):
   /**
    * Create a read-only {@link IModel}. Usage:
    * <pre>
    * {@code
    *     LambdaModel.of(person::getName)
    * }
    * </pre>
    * Note that {@link IModel} is a {@code FunctionalInterface} and you can
    * also use a lambda directly as a model.
    *
    * @param getter used to get value
    * @return model
    *
    * @param <T> model object type
    */
   public static <T> IModel<T> of(SerializableSupplier<T> getter)
   {
       return getter::get;
   }

Emond


On donderdag 10 november 2016 21:40:58 CET Sven Meier wrote:
> If Martijn needs this, I'd prefer just to add another factory method:
> 
>      /**
>       * Create a read-only {@link LambdaModel}. Usage:
>       * <pre>
>       * {@code
>       *     LambdaModel.of(person::getName)
>       * }
>       * </pre>
>       *
>       * @param getter used to get value
>       * @return model
>       *
>       * @param <T> model object type
>       */
>      public static <T> IModel<T> of(SerializableSupplier<T> getter)
>      {
>          return new LambdaModel<>(getter, (t) -> { throw new
> UnsupportedOperationException(); });
>      }
> 
> And the setter should throw the exception.
> 
> Have fun
> Sven
> 
> Am 10.11.2016 um 21:34 schrieb Martin Grigorov:
> > I think there is no need of this change.
> > But if others believe it's needed then #setObject should throw an
> > exception
> > as in IModel.
> > 
> > On Nov 10, 2016 10:24 PM, "Martijn Dashorst" <ma...@gmail.com>
> > 
> > wrote:
> >> So are we pro/against expanding LambdaModel for support of a read only
> >> variant?
> >> 
> >> Reasons against:
> >>   - not necessary with IModel as a functional interface
> >>   - multiple ways to do things
> >> 
> >> Reasons pro:
> >>   - IModel version may not be as clear as a Lambda model
> >>   - IModel version may not be as obvious a choice (years of experience
> >> 
> >> with Java < 8 and Wicket < 8)
> >> 
> >> Proposed patch:
> >> 
> >> diff --git a/wicket-core/src/main/java/org/apache/wicket/model/
> >> LambdaModel.java
> >> b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
> >> index 8fb9d6a..ece4fe5 100644
> >> --- a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
> >> +++ b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
> >> @@ -53,6 +53,19 @@ public class LambdaModel<T> implements IModel<T>
> >> 
> >>    this.setter = Args.notNull(setter, "setter");
> >>    }
> >> 
> >> + /**
> >> + * Construct the model, using the given supplier and consumer as
> >> + * implementation for getObject and setObject.
> >> + *
> >> + * @param getter Used for the getObject() method.
> >> + * @param setter Used for the setObject(T object) method.
> >> + */
> >> + public LambdaModel(SerializableSupplier<T> getter)
> >> + {
> >> + this.getter = Args.notNull(getter, "getter");
> >> + this.setter = null;
> >> + }
> >> +
> >> 
> >>    @Override
> >>    public T getObject()
> >>    {
> >> 
> >> @@ -62,7 +75,8 @@ public class LambdaModel<T> implements IModel<T>
> >> 
> >>    @Override
> >>    public void setObject(T t)
> >>    {
> >> 
> >> - setter.accept(t);
> >> + if(setter != null)
> >> + setter.accept(t);
> >> 
> >>    }
> >>    
> >>    @Override
> >> 
> >> @@ -114,6 +128,24 @@ public class LambdaModel<T> implements IModel<T>
> >> 
> >>    }
> >>    
> >>    /**
> >> 
> >> + * Create a read only {@link LambdaModel}. Usage:
> >> + * <pre>
> >> + * {@code
> >> + * LambdaModel.of(person::getName)
> >> + * }
> >> + * </pre>
> >> + *
> >> + * @param getter used to get value
> >> + * @return model
> >> + *
> >> + * @param <T> model object type
> >> + */
> >> + public static <T> IModel<T> of(SerializableSupplier<T> getter)
> >> + {
> >> + return new LambdaModel<>(getter);
> >> + }
> >> +
> >> + /**
> >> 
> >>    * Create a {@link LambdaModel} for a given target. Usage:
> >>    * <pre>
> >>    * {@code



Re: LambdaModel for readonly models

Posted by Martin Grigorov <mg...@apache.org>.
On Thu, Nov 10, 2016 at 9:40 PM, Sven Meier <sv...@meiers.net> wrote:

> If Martijn needs this, I'd prefer just to add another factory method:
>
>     /**
>      * Create a read-only {@link LambdaModel}. Usage:
>      * <pre>
>      * {@code
>      *     LambdaModel.of(person::getName)
>      * }
>      * </pre>
>      *
>      * @param getter used to get value
>      * @return model
>      *
>      * @param <T> model object type
>      */
>     public static <T> IModel<T> of(SerializableSupplier<T> getter)
>     {
>         return new LambdaModel<>(getter, (t) -> { throw new
> UnsupportedOperationException(); });
>     }
>
> And the setter should throw the exception.
>

+1


>
> Have fun
> Sven
>
>
>
>
> Am 10.11.2016 um 21:34 schrieb Martin Grigorov:
>
>> I think there is no need of this change.
>> But if others believe it's needed then #setObject should throw an
>> exception
>> as in IModel.
>>
>> On Nov 10, 2016 10:24 PM, "Martijn Dashorst" <ma...@gmail.com>
>> wrote:
>>
>> So are we pro/against expanding LambdaModel for support of a read only
>>> variant?
>>>
>>> Reasons against:
>>>   - not necessary with IModel as a functional interface
>>>   - multiple ways to do things
>>>
>>> Reasons pro:
>>>   - IModel version may not be as clear as a Lambda model
>>>   - IModel version may not be as obvious a choice (years of experience
>>> with Java < 8 and Wicket < 8)
>>>
>>> Proposed patch:
>>>
>>> diff --git a/wicket-core/src/main/java/org/apache/wicket/model/
>>> LambdaModel.java
>>> b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>>> index 8fb9d6a..ece4fe5 100644
>>> --- a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>>> +++ b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>>> @@ -53,6 +53,19 @@ public class LambdaModel<T> implements IModel<T>
>>>    this.setter = Args.notNull(setter, "setter");
>>>    }
>>>
>>> + /**
>>> + * Construct the model, using the given supplier and consumer as
>>> + * implementation for getObject and setObject.
>>> + *
>>> + * @param getter Used for the getObject() method.
>>> + * @param setter Used for the setObject(T object) method.
>>> + */
>>> + public LambdaModel(SerializableSupplier<T> getter)
>>> + {
>>> + this.getter = Args.notNull(getter, "getter");
>>> + this.setter = null;
>>> + }
>>> +
>>>    @Override
>>>    public T getObject()
>>>    {
>>> @@ -62,7 +75,8 @@ public class LambdaModel<T> implements IModel<T>
>>>    @Override
>>>    public void setObject(T t)
>>>    {
>>> - setter.accept(t);
>>> + if(setter != null)
>>> + setter.accept(t);
>>>    }
>>>
>>>    @Override
>>> @@ -114,6 +128,24 @@ public class LambdaModel<T> implements IModel<T>
>>>    }
>>>
>>>    /**
>>> + * Create a read only {@link LambdaModel}. Usage:
>>> + * <pre>
>>> + * {@code
>>> + * LambdaModel.of(person::getName)
>>> + * }
>>> + * </pre>
>>> + *
>>> + * @param getter used to get value
>>> + * @return model
>>> + *
>>> + * @param <T> model object type
>>> + */
>>> + public static <T> IModel<T> of(SerializableSupplier<T> getter)
>>> + {
>>> + return new LambdaModel<>(getter);
>>> + }
>>> +
>>> + /**
>>>    * Create a {@link LambdaModel} for a given target. Usage:
>>>    * <pre>
>>>    * {@code
>>>
>>>
>

Re: LambdaModel for readonly models

Posted by Sven Meier <sv...@meiers.net>.
If Martijn needs this, I'd prefer just to add another factory method:

     /**
      * Create a read-only {@link LambdaModel}. Usage:
      * <pre>
      * {@code
      *     LambdaModel.of(person::getName)
      * }
      * </pre>
      *
      * @param getter used to get value
      * @return model
      *
      * @param <T> model object type
      */
     public static <T> IModel<T> of(SerializableSupplier<T> getter)
     {
         return new LambdaModel<>(getter, (t) -> { throw new 
UnsupportedOperationException(); });
     }

And the setter should throw the exception.

Have fun
Sven



Am 10.11.2016 um 21:34 schrieb Martin Grigorov:
> I think there is no need of this change.
> But if others believe it's needed then #setObject should throw an exception
> as in IModel.
>
> On Nov 10, 2016 10:24 PM, "Martijn Dashorst" <ma...@gmail.com>
> wrote:
>
>> So are we pro/against expanding LambdaModel for support of a read only
>> variant?
>>
>> Reasons against:
>>   - not necessary with IModel as a functional interface
>>   - multiple ways to do things
>>
>> Reasons pro:
>>   - IModel version may not be as clear as a Lambda model
>>   - IModel version may not be as obvious a choice (years of experience
>> with Java < 8 and Wicket < 8)
>>
>> Proposed patch:
>>
>> diff --git a/wicket-core/src/main/java/org/apache/wicket/model/
>> LambdaModel.java
>> b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>> index 8fb9d6a..ece4fe5 100644
>> --- a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>> +++ b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
>> @@ -53,6 +53,19 @@ public class LambdaModel<T> implements IModel<T>
>>    this.setter = Args.notNull(setter, "setter");
>>    }
>>
>> + /**
>> + * Construct the model, using the given supplier and consumer as
>> + * implementation for getObject and setObject.
>> + *
>> + * @param getter Used for the getObject() method.
>> + * @param setter Used for the setObject(T object) method.
>> + */
>> + public LambdaModel(SerializableSupplier<T> getter)
>> + {
>> + this.getter = Args.notNull(getter, "getter");
>> + this.setter = null;
>> + }
>> +
>>    @Override
>>    public T getObject()
>>    {
>> @@ -62,7 +75,8 @@ public class LambdaModel<T> implements IModel<T>
>>    @Override
>>    public void setObject(T t)
>>    {
>> - setter.accept(t);
>> + if(setter != null)
>> + setter.accept(t);
>>    }
>>
>>    @Override
>> @@ -114,6 +128,24 @@ public class LambdaModel<T> implements IModel<T>
>>    }
>>
>>    /**
>> + * Create a read only {@link LambdaModel}. Usage:
>> + * <pre>
>> + * {@code
>> + * LambdaModel.of(person::getName)
>> + * }
>> + * </pre>
>> + *
>> + * @param getter used to get value
>> + * @return model
>> + *
>> + * @param <T> model object type
>> + */
>> + public static <T> IModel<T> of(SerializableSupplier<T> getter)
>> + {
>> + return new LambdaModel<>(getter);
>> + }
>> +
>> + /**
>>    * Create a {@link LambdaModel} for a given target. Usage:
>>    * <pre>
>>    * {@code
>>


Re: LambdaModel for readonly models

Posted by Martin Grigorov <mg...@apache.org>.
I think there is no need of this change.
But if others believe it's needed then #setObject should throw an exception
as in IModel.

On Nov 10, 2016 10:24 PM, "Martijn Dashorst" <ma...@gmail.com>
wrote:

> So are we pro/against expanding LambdaModel for support of a read only
> variant?
>
> Reasons against:
>  - not necessary with IModel as a functional interface
>  - multiple ways to do things
>
> Reasons pro:
>  - IModel version may not be as clear as a Lambda model
>  - IModel version may not be as obvious a choice (years of experience
> with Java < 8 and Wicket < 8)
>
> Proposed patch:
>
> diff --git a/wicket-core/src/main/java/org/apache/wicket/model/
> LambdaModel.java
> b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
> index 8fb9d6a..ece4fe5 100644
> --- a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
> +++ b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
> @@ -53,6 +53,19 @@ public class LambdaModel<T> implements IModel<T>
>   this.setter = Args.notNull(setter, "setter");
>   }
>
> + /**
> + * Construct the model, using the given supplier and consumer as
> + * implementation for getObject and setObject.
> + *
> + * @param getter Used for the getObject() method.
> + * @param setter Used for the setObject(T object) method.
> + */
> + public LambdaModel(SerializableSupplier<T> getter)
> + {
> + this.getter = Args.notNull(getter, "getter");
> + this.setter = null;
> + }
> +
>   @Override
>   public T getObject()
>   {
> @@ -62,7 +75,8 @@ public class LambdaModel<T> implements IModel<T>
>   @Override
>   public void setObject(T t)
>   {
> - setter.accept(t);
> + if(setter != null)
> + setter.accept(t);
>   }
>
>   @Override
> @@ -114,6 +128,24 @@ public class LambdaModel<T> implements IModel<T>
>   }
>
>   /**
> + * Create a read only {@link LambdaModel}. Usage:
> + * <pre>
> + * {@code
> + * LambdaModel.of(person::getName)
> + * }
> + * </pre>
> + *
> + * @param getter used to get value
> + * @return model
> + *
> + * @param <T> model object type
> + */
> + public static <T> IModel<T> of(SerializableSupplier<T> getter)
> + {
> + return new LambdaModel<>(getter);
> + }
> +
> + /**
>   * Create a {@link LambdaModel} for a given target. Usage:
>   * <pre>
>   * {@code
>

Re: LambdaModel for readonly models

Posted by Martijn Dashorst <ma...@gmail.com>.
So are we pro/against expanding LambdaModel for support of a read only variant?

Reasons against:
 - not necessary with IModel as a functional interface
 - multiple ways to do things

Reasons pro:
 - IModel version may not be as clear as a Lambda model
 - IModel version may not be as obvious a choice (years of experience
with Java < 8 and Wicket < 8)

Proposed patch:

diff --git a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
index 8fb9d6a..ece4fe5 100644
--- a/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
+++ b/wicket-core/src/main/java/org/apache/wicket/model/LambdaModel.java
@@ -53,6 +53,19 @@ public class LambdaModel<T> implements IModel<T>
  this.setter = Args.notNull(setter, "setter");
  }

+ /**
+ * Construct the model, using the given supplier and consumer as
+ * implementation for getObject and setObject.
+ *
+ * @param getter Used for the getObject() method.
+ * @param setter Used for the setObject(T object) method.
+ */
+ public LambdaModel(SerializableSupplier<T> getter)
+ {
+ this.getter = Args.notNull(getter, "getter");
+ this.setter = null;
+ }
+
  @Override
  public T getObject()
  {
@@ -62,7 +75,8 @@ public class LambdaModel<T> implements IModel<T>
  @Override
  public void setObject(T t)
  {
- setter.accept(t);
+ if(setter != null)
+ setter.accept(t);
  }

  @Override
@@ -114,6 +128,24 @@ public class LambdaModel<T> implements IModel<T>
  }

  /**
+ * Create a read only {@link LambdaModel}. Usage:
+ * <pre>
+ * {@code
+ * LambdaModel.of(person::getName)
+ * }
+ * </pre>
+ *
+ * @param getter used to get value
+ * @return model
+ *
+ * @param <T> model object type
+ */
+ public static <T> IModel<T> of(SerializableSupplier<T> getter)
+ {
+ return new LambdaModel<>(getter);
+ }
+
+ /**
  * Create a {@link LambdaModel} for a given target. Usage:
  * <pre>
  * {@code