You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@isis.apache.org by Hector Fabio Meza <he...@smartools.com.co> on 2016/11/19 03:14:33 UTC

DTO inside View Model

Based on the suggestions I got after my last mail, I am now in the
process of implementing a View Model. 
I'm basing my implementation on the ViewModels in isis-app-todoapp, and
the YouTube videos about View Models. 

So far I've been able to create a View Model that shows a list of
objects, but ran into a problem when trying to add a Filter
functionality. It's probably due to a misunderstanding on how ViewModels
work, so I'd like to make sure my approach is correct. 

I created a DTO that stores the fields I want to use as a filter, and
annotated it with JAXB XML annotations (I think this is necessary due to
the ViewModels using a String representation at some point). 

Then I created an attribute in the ViewModel of type DTO, and created an
action "Filter" that asks the user for values for the DTO's fields and
stores them in the ViewModel's attribute, and then returns "this". 

The problem appears when the getObjects method is called after reloading
the page. I try to access the attribute of type DTO and get the values
that "Filter" set, to show the list with only the values that meet the
criteria, but at this point all the DTO's fields are null. 

TodoApp's ToDoItemsByDateRangeViewModel.java has a DateRange attribute,
which leads me to think that ViewModels can store objects as attributes
and use their values for processing, but in my case it seems that my
FilterDTO is not being stored between action invocations. 

The DTO is initialized in the ViewModels constructor, so I'm wondering
if after returning "this" from an action, the object is recreated at
some point? 

Or maybe I'm not doing this correctly, or ViewModels are stateless,
maybe when dealing with non persistent objects? 

Thank you.

-- 
Hector Fabio Meza

R&D LEAD SMARTOOLS 
(57) 300 2254455= [1] 
Skype: hectorf.meza 
www.smartools.com.co [2] 

 

Links:
------
[1] tel:%2857%29%20300%206815404
[2] http://www.smartools.com.co/

Re: DTO inside View Model

Posted by Hector Fabio Meza <he...@smartools.com.co>.
Thanks a lot, Dan! With that change, everything started working
perfectly. 

El 2016-11-27 10:19, Dan Haywood escribi�:

> Thanks for the example. 
> 
> You can fix this as follows: 
> 
> //@ViewModel 
> @XmlRootElement 
> public class SimpleViewModel { 
> 
> private SimpleObjectDTO filter; 
> 
> ... 
> } 
> 
> The issue, is that @ViewModel will only serialize out the state of scalar value types (strings, dates etc).  The SimpleObjectDTO, being a reference type, is ignored.  It's confusing, because it looks like the value of the filter (SimpleObjectDTO) has been set and serialized correctly, however I think you would find that just refreshing the SimpleObjectViewModel causes its state to get lost once more. 
> 
> Changing @ViewModel to @XmlRootElement causes the entire graph of objects' state, including SimpleObjectDTO, to be captured.   
> 
> ~~~ 
> 
> Another way to check this: without making the above change, alter the SimpleObjectViewModel.layout.xml so that you have the regular title, by adding <domainObject/>, eg: 
> 
> <bs3:row> 
> <bs3:col span="11" unreferencedActions="true"> 
> <domainObject/> 
> ... 
> </bs3:row> 
> 
> Then, do the following: 
> 
> - call filter action, set a value for the name of the SimpleObjectDTO filter, eg "Foo" 
> - the click on the "ViewModel" title 
> - now inspect the property of SimpleObjectDTO filter... it will be null. 
> 
> Change @ViewModel to @XmlRootElement, and it should be retained 
> 
> HTH 
> 
> Dan

-- 
Hector Fabio Meza

R&D LEAD SMARTOOLS 
(57) 300 2254455 [1] 
Skype: hectorf.meza 
www.smartools.com.co [2] 

 

Links:
------
[1] tel:%2857%29%20300%206815404
[2] http://www.smartools.com.co/

Re: DTO inside View Model

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
Thanks for the example.

You can fix this as follows:


//@ViewModel
@XmlRootElement
public class SimpleViewModel {

private SimpleObjectDTO filter;

        ...
}


The issue, is that @ViewModel will only serialize out the state of scalar
value types (strings, dates etc).  The SimpleObjectDTO, being a reference
type, is ignored.  It's confusing, because it looks like the value of the
filter (SimpleObjectDTO) has been set and serialized correctly, however I
think you would find that just refreshing the SimpleObjectViewModel causes
its state to get lost once more.

Changing @ViewModel to @XmlRootElement causes the entire graph of objects'
state, including SimpleObjectDTO, to be captured.


~~~

Another way to check this: without making the above change, alter the
SimpleObjectViewModel.layout.xml so that you have the regular title, by
adding <domainObject/>, eg:

<bs3:row>
<bs3:col span="11" unreferencedActions="true">
            <domainObject/>
                 ...
         </bs3:row>

Then, do the following:

- call filter action, set a value for the name of the SimpleObjectDTO
filter, eg "Foo"
- the click on the "ViewModel" title
- now inspect the property of SimpleObjectDTO filter... it will be null.

Change @ViewModel to @XmlRootElement, and it should be retained

HTH

Dan










On 27 November 2016 at 00:27, Hector Fabio Meza <
hector.meza@smartools.com.co> wrote:

> Hi, Dan,
>
> Thank you for your suggestions. Im using the @ViewModel annotation on the
> ViewModel. The DTO I´m trying to use as a filter is annotated with
> @DomainObject(nature=Nature.VIEW_MODEL) and javax.xml annotations.
>
> After doing some more tests, I think the problem is not in the model´s
> state, since the viewer shows the correct value for the properties. Now I
> suspect my problem has to do with the point of the lifecycle where methods
> are called.
>
> I´ve included a link to a SimpleObjects app where I added a simplified
> case of my ViewModel (SimpleViewModel.java). It is intended to be a single
> entry point for an entity, so it has an action that returns a collection
> with all entities, a "create" action that allows the user to create a new
> SimpleObject and a "filter" action that asks the user for a "name" and
> stores it in thje model´s DTO.
>
> The problem is that when I try to access the DTO´s fields in the list
> action, it shows all attributes as null while the Viewer does show me the
> value I entered.
>
> I think maybe the getObjects method is being called before the model´s
> state has been recreated?
>
> ---------------------------------------------
>
>
>     private SimpleObjectDTO filter;
>
>      public SimpleViewModel filter(
>             final @ParameterLayout(named = "Name") @Parameter(optionality
> = Optionality.OPTIONAL) String name) {
>
>         filter = new SimpleObjectDTO();
>
>         filter.setName(name);
>
>         filter.setDoFilter(true);
>
>         return this;
>     }
>
>     public List<SimpleObject> getObjects() {
>         System.out.println("filter : " + filter);
>
>         return simpleObjects.listAll();
>
>     }
>
>     filter : SimpleDTO [name=null, doFilter=false]
>     19:23:29,147  [Native               qtp1615535645-20 DEBUG]  SELECT
> 'domainapp.dom.simple.SimpleObject' AS
> "NUCLEUS_TYPE","A0"."name","A0"."notes","A0"."id","A0"."version" FROM
> "simple"."SimpleObject" "A0"
>
> ----------------------------------------------
>
> https://www.dropbox.com/s/xiot10oskfpn5vm/SimpleViewModel.zip?dl=0
>
>
> El 2016-11-26 13:00, Dan Haywood escribió:
>
> Hi Hector,
>
> There are a couple of different ways to write view models, and they have
> different capabilities.  At some point I anticipate we'll deprecate
> some/most of these... we are where we are.
>
> What's common about all the view models is that the view model's state is
> converted into the object's OID: this is visible in the URL of the object
> (either in Wicket viewer or REST API).  When the view model is next
> interacted with, then the framework recreates the view model from that OID,
> then invokes the action/property edit.
>
> Which state is extracted into the OID/used to rehydrate the view model
> subsequenty varies by implementation:
>
> - if your code implements ViewModel interface, then you have full control
> (the viewModelInit and viewModelMemento methods are basically reciprocals
> of each other)
>
> - if your code is annotated with @ViewModel or with
> @DomainObject(nature=VIEW_MODEL | EXTERNAL_ENTITY | INMEMORY_ENTITY),
> then the framework will use the state of any properties of the domain
> object; however collections are ignored
>
> - if your code is annotated with @XmlRootElement, then we use JAXB to
> serialize the entire object graph; in practice this means both properties
> and collections, ignoring fields annotated with @XmlTransient.  Any
> references to entities are converted to bookmarks, assuming that those
> entities are themselves annotated with @XmlJavaTypeAdapter(
> PersistentEntityAdapter.class)
>
> Hopefully that's enough for you to figure out what's going on.  But if
> not, perhaps you could post some code or, even better, create a simple
> example app that demonstrates the issue.
>
> Cheers
> Dan
>
>
>
>
>
> --
>
> *Hector Fabio Meza*
> *R&D Lead smartools*
> (57) 300 2254455 <%2857%29%20300%206815404>
> Skype: hectorf.meza
> www.smartools.com.co
>
>

Re: DTO inside View Model

Posted by Hector Fabio Meza <he...@smartools.com.co>.
Hi, Dan, 

Thank you for your suggestions. Im using the @ViewModel annotation on
the ViewModel. The DTO I�m trying to use as a filter is annotated with
@DomainObject(nature=Nature.VIEW_MODEL) and javax.xml annotations. 

After doing some more tests, I think the problem is not in the model�s
state, since the viewer shows the correct value for the properties. Now
I suspect my problem has to do with the point of the lifecycle where
methods are called. 

I�ve included a link to a SimpleObjects app where I added a simplified
case of my ViewModel (SimpleViewModel.java). It is intended to be a
single entry point for an entity, so it has an action that returns a
collection with all entities, a "create" action that allows the user to
create a new SimpleObject and a "filter" action that asks the user for a
"name" and stores it in thje model�s DTO. 

The problem is that when I try to access the DTO�s fields in the list
action, it shows all attributes as null while the Viewer does show me
the value I entered. 

I think maybe the getObjects method is being called before the model�s
state has been recreated? 

--------------------------------------------- 

    private SimpleObjectDTO filter; 

     public SimpleViewModel filter(
            final @ParameterLayout(named = "Name")
@Parameter(optionality = Optionality.OPTIONAL) String name) {

        filter = new SimpleObjectDTO();

        filter.setName(name);

        filter.setDoFilter(true);

        return this;
    } 

    public List<SimpleObject> getObjects() {
        System.out.println("filter : " + filter);

        return simpleObjects.listAll();

    } 

    filter : SimpleDTO [name=null, doFilter=false]
    19:23:29,147  [Native               qtp1615535645-20 DEBUG]  SELECT
'domainapp.dom.simple.SimpleObject' AS          
"NUCLEUS_TYPE","A0"."name","A0"."notes","A0"."id","A0"."version" FROM
"simple"."SimpleObject" "A0" 

---------------------------------------------- 

https://www.dropbox.com/s/xiot10oskfpn5vm/SimpleViewModel.zip?dl=0 

El 2016-11-26 13:00, Dan Haywood escribi�:

> Hi Hector, 
> 
> There are a couple of different ways to write view models, and they have different capabilities.  At some point I anticipate we'll deprecate some/most of these... we are where we are. 
> 
> What's common about all the view models is that the view model's state is converted into the object's OID: this is visible in the URL of the object (either in Wicket viewer or REST API).  When the view model is next interacted with, then the framework recreates the view model from that OID, then invokes the action/property edit. 
> 
> Which state is extracted into the OID/used to rehydrate the view model subsequenty varies by implementation: 
> 
> - if your code implements ViewModel interface, then you have full control (the viewModelInit and viewModelMemento methods are basically reciprocals of each other) 
> 
> - if your code is annotated with @ViewModel or with @DomainObject(nature=VIEW_MODEL | EXTERNAL_ENTITY | INMEMORY_ENTITY), then the framework will use the state of any properties of the domain object; however collections are ignored 
> 
> - if your code is annotated with @XmlRootElement, then we use JAXB to serialize the entire object graph; in practice this means both properties and collections, ignoring fields annotated with @XmlTransient.  Any references to entities are converted to bookmarks, assuming that those entities are themselves annotated with @XmlJavaTypeAdapter(PersistentEntityAdapter.class) 
> 
> Hopefully that's enough for you to figure out what's going on.  But if not, perhaps you could post some code or, even better, create a simple example app that demonstrates the issue. 
> 
> Cheers 
> Dan

-- 
Hector Fabio Meza

R&D LEAD SMARTOOLS 
(57) 300 2254455 [1] 
Skype: hectorf.meza 
www.smartools.com.co [2] 

 

Links:
------
[1] tel:%2857%29%20300%206815404
[2] http://www.smartools.com.co/

Re: DTO inside View Model

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
Hi Hector,

There are a couple of different ways to write view models, and they have
different capabilities.  At some point I anticipate we'll deprecate
some/most of these... we are where we are.

What's common about all the view models is that the view model's state is
converted into the object's OID: this is visible in the URL of the object
(either in Wicket viewer or REST API).  When the view model is next
interacted with, then the framework recreates the view model from that OID,
then invokes the action/property edit.

Which state is extracted into the OID/used to rehydrate the view model
subsequenty varies by implementation:

- if your code implements ViewModel interface, then you have full control
(the viewModelInit and viewModelMemento methods are basically reciprocals
of each other)

- if your code is annotated with @ViewModel or with
@DomainObject(nature=VIEW_MODEL | EXTERNAL_ENTITY | INMEMORY_ENTITY), then
the framework will use the state of any properties of the domain object;
however collections are ignored

- if your code is annotated with @XmlRootElement, then we use JAXB to
serialize the entire object graph; in practice this means both properties
and collections, ignoring fields annotated with @XmlTransient.  Any
references to entities are converted to bookmarks, assuming that those
entities are themselves annotated
with @XmlJavaTypeAdapter(PersistentEntityAdapter.class)

Hopefully that's enough for you to figure out what's going on.  But if not,
perhaps you could post some code or, even better, create a simple example
app that demonstrates the issue.

Cheers
Dan







On 19 November 2016 at 03:14, Hector Fabio Meza <
hector.meza@smartools.com.co> wrote:

> Based on the suggestions I got after my last mail, I am now in the process
> of implementing a View Model.
> I'm basing my implementation on the ViewModels in isis-app-todoapp, and
> the YouTube videos about View Models.
>
> So far I've been able to create a View Model that shows a list of objects,
> but ran into a problem when trying to add a Filter functionality. It's
> probably due to a misunderstanding on how ViewModels work, so I'd like to
> make sure my approach is correct.
>
> I created a DTO that stores the fields I want to use as a filter, and
> annotated it with JAXB XML annotations (I think this is necessary due to
> the ViewModels using a String representation at some point).
>
> Then I created an attribute in the ViewModel of type DTO, and created an
> action "Filter" that asks the user for values for the DTO's fields and
> stores them in the ViewModel's attribute, and then returns "this".
>
> The problem appears when the getObjects method is called after reloading
> the page. I try to access the attribute of type DTO and get the values that
> "Filter" set, to show the list with only the values that meet the criteria,
> but at this point all the DTO's fields are null.
>
> TodoApp's ToDoItemsByDateRangeViewModel.java has a DateRange attribute,
> which leads me to think that ViewModels can store objects as attributes and
> use their values for processing, but in my case it seems that my FilterDTO
> is not being stored between action invocations.
>
> The DTO is initialized in the ViewModels constructor, so I'm wondering if
> after returning "this" from an action, the object is recreated at some
> point?
>
> Or maybe I'm not doing this correctly, or ViewModels are stateless, maybe
> when dealing with non persistent objects?
>
> Thank you.
> --
>
> *Hector Fabio Meza*
> *R&D Lead smartools*
> (57) 300 2254455= <%2857%29%20300%206815404>
> Skype: hectorf.meza
> www.smartools.com.co
>
>