You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@isis.apache.org by Boris Toninski <bo...@orangedot.bg> on 2015/05/07 15:16:15 UTC
What is the proper way to implement calculated property
I have a timestamp property called "end date". I want when the user views/enters it, to work only with the date part, but to be stored in the DB as a timestamp. Here is how I tried to implement this in the entity class:
@javax.jdo.annotations.Persistent(defaultFetchGroup="true")
private DateTime endDate;
@javax.jdo.annotations.Column(name = "end_date", allowsNull = "true")
@Property(hidden = Where.ALL_TABLES)
public DateTime getEndDate() {
return endDate;
}
public void setEndDate(DateTime endDate) {
this.endDate = endDate;
}
@MemberOrder(sequence = "5")
@Property(notPersisted = true)
@PropertyLayout(named = "End date")
public LocalDate getLocalEndDate() {
return convertEndDate(getEndDate()); //converts it to Toronto time zone and cuts the time part
}
public void setLocalEndDate(LocalDate localEndDate) {
setEndDate(convertEndDate(localEndDate)); //converts it to 23:59:59 in Toronto time zone
}
This way the setting of the date does not works. I debugged it and found that right after setting the value, the framework sets it back to null.
I have one more property - "start date" which is implemented the same way and it works.
Initially I have implemented this without the getter and the setter for the field itself (no getEndDate and setEndDate). And working directly with the field, and it was working, but when I enabled auditing, the auditing for this property didn't work.
Please advise what will be the right way to implement it.
Thanks in advance!
RE: What is the proper way to implement calculated property
Posted by Boris Toninski <bo...@orangedot.bg>.
Thanks Dan,
I will try to reproduce the problem in a new project created from the simpleapp archetype.
-----Original Message-----
From: Dan Haywood [mailto:dan@haywood-associates.co.uk]
Sent: Monday, May 11, 2015 12:19 PM
To: users
Subject: Re: What is the proper way to implement calculated property
Hi Boris,
sorry you haven't had a reply before now. Let me make amends.
On 7 May 2015 at 14:16, Boris Toninski <bo...@orangedot.bg> wrote:
> I have a timestamp property called "end date". I want when the user
> views/enters it, to work only with the date part, but to be stored in
> the DB as a timestamp. Here is how I tried to implement this in the
> entity
> class:
>
> @javax.jdo.annotations.Persistent(defaultFetchGroup="true")
> private DateTime endDate;
>
>
> @javax.jdo.annotations.Column(name = "end_date", allowsNull = "true")
> @Property(hidden = Where.ALL_TABLES) public DateTime getEndDate() {
> return endDate;
> }
>
> public void setEndDate(DateTime endDate) {
> this.endDate = endDate;
> }
>
>
above looks ok. DateTime requires the JDO @Persistent annotation. Per [1] DFG is true by default so that bit is not required.
> @MemberOrder(sequence = "5")
> @Property(notPersisted = true)
> @PropertyLayout(named = "End date")
> public LocalDate getLocalEndDate() {
> return convertEndDate(getEndDate()); //converts it to Toronto time
> zone and cuts the time part }
>
> public void setLocalEndDate(LocalDate localEndDate) {
> setEndDate(convertEndDate(localEndDate)); //converts it to
> 23:59:59 in Toronto time zone }
>
>
I think you raised a ticket about our possibly broken timezone handling, so I'll ignore that bit.
> This way the setting of the date does not works. I debugged it and
> found that right after setting the value, the framework sets it back to null.
>
> I have one more property - "start date" which is implemented the same
> way and it works.
>
> The code above does look correct to me (assuming that
"convertEndDate(...)" does something sensible).
You said that a "startDate" property works fine, so I find it hard to understand why following the same pattern would break elsewhere.
If you can prepare a test case (use our simpleapp archetype as a starting
point) and upload to github, then I'll take a look.
> Initially I have implemented this without the getter and the setter
> for the field itself (no getEndDate and setEndDate).
That's fine; DataNucleus will continue to work ok. Because there is no getter and setter, it will not be part of the Isis metamodel (there needs to be at least a getter for that).
> And working directly with the field, and it was working, but when I
> enabled auditing, the auditing for this property didn't work.
>
>
Auditing works as follows:
- we rely on DataNucleus to tell us that the object is dirtied (the various IsisTransaction#enlist{Created/Updating/Deleted} methods called from the
FrameworkSynchronizer)
- in terms of which audit records to create, Isis loops through the properties that it knows about (so any fields without a getter will be
ignored)
- also, there is an explicit check [2] to exclude any properties that are marked as not persisted.
To be honest, I can't exactly remember the reason for that check [2], other than probably the rationale that if the underlying data is changed and audited, then there's no need to also audit any derived data.
I don't imagine there would be many negative consequences about making this configurable via isis.properties (though we'd leave the default behaviour as it is). So if you want to raise a ticket / contribute a pull request, then do go ahead.
Cheers
Dan
> Please advise what will be the right way to implement it.
>
> Thanks in advance!
>
[1] http://www.datanucleus.org/products/datanucleus/jdo/types.html
[2]
https://github.com/apache/isis/blob/3183d013d3d756c098ff96ace23951336e12aad6/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java#L1355
Re: What is the proper way to implement calculated property
Posted by Dan Haywood <da...@haywood-associates.co.uk>.
Hi Boris,
sorry you haven't had a reply before now. Let me make amends.
On 7 May 2015 at 14:16, Boris Toninski <bo...@orangedot.bg> wrote:
> I have a timestamp property called "end date". I want when the user
> views/enters it, to work only with the date part, but to be stored in the
> DB as a timestamp. Here is how I tried to implement this in the entity
> class:
>
> @javax.jdo.annotations.Persistent(defaultFetchGroup="true")
> private DateTime endDate;
>
>
> @javax.jdo.annotations.Column(name = "end_date", allowsNull = "true")
> @Property(hidden = Where.ALL_TABLES)
> public DateTime getEndDate() {
> return endDate;
> }
>
> public void setEndDate(DateTime endDate) {
> this.endDate = endDate;
> }
>
>
above looks ok. DateTime requires the JDO @Persistent annotation. Per [1]
DFG is true by default so that bit is not required.
> @MemberOrder(sequence = "5")
> @Property(notPersisted = true)
> @PropertyLayout(named = "End date")
> public LocalDate getLocalEndDate() {
> return convertEndDate(getEndDate()); //converts it to Toronto time
> zone and cuts the time part
> }
>
> public void setLocalEndDate(LocalDate localEndDate) {
> setEndDate(convertEndDate(localEndDate)); //converts it to 23:59:59 in
> Toronto time zone
> }
>
>
I think you raised a ticket about our possibly broken timezone handling, so
I'll ignore that bit.
> This way the setting of the date does not works. I debugged it and found
> that right after setting the value, the framework sets it back to null.
>
> I have one more property - "start date" which is implemented the same way
> and it works.
>
> The code above does look correct to me (assuming that
"convertEndDate(...)" does something sensible).
You said that a "startDate" property works fine, so I find it hard to
understand why following the same pattern would break elsewhere.
If you can prepare a test case (use our simpleapp archetype as a starting
point) and upload to github, then I'll take a look.
> Initially I have implemented this without the getter and the setter for
> the field itself (no getEndDate and setEndDate).
That's fine; DataNucleus will continue to work ok. Because there is no
getter and setter, it will not be part of the Isis metamodel (there needs
to be at least a getter for that).
> And working directly with the field, and it was working, but when I
> enabled auditing, the auditing for this property didn't work.
>
>
Auditing works as follows:
- we rely on DataNucleus to tell us that the object is dirtied (the various
IsisTransaction#enlist{Created/Updating/Deleted} methods called from the
FrameworkSynchronizer)
- in terms of which audit records to create, Isis loops through the
properties that it knows about (so any fields without a getter will be
ignored)
- also, there is an explicit check [2] to exclude any properties that are
marked as not persisted.
To be honest, I can't exactly remember the reason for that check [2], other
than probably the rationale that if the underlying data is changed and
audited, then there's no need to also audit any derived data.
I don't imagine there would be many negative consequences about making this
configurable via isis.properties (though we'd leave the default behaviour
as it is). So if you want to raise a ticket / contribute a pull request,
then do go ahead.
Cheers
Dan
> Please advise what will be the right way to implement it.
>
> Thanks in advance!
>
[1] http://www.datanucleus.org/products/datanucleus/jdo/types.html
[2]
https://github.com/apache/isis/blob/3183d013d3d756c098ff96ace23951336e12aad6/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java#L1355