There is a big improvement on post-update change capturing API
("cayenne-commitlog" module [1]). However pre-update does require manual
inspection of the object vs. saved state.
Andrus
[1] https://cayenne.apache.org/docs/4.0/cayenne-guide/#ext-commit-log
> On Jan 22, 2019, at 4:42 PM, Andrew Willerding <[email protected]>
> wrote:
>
> Thank you Maik.
>
> I was hoping for something much simpler than this and that's baked into
> Cayenne.
>
>
> On 2019-01-22 11:19 a.m., Maik Musall wrote:
>> Hi Andrew,
>>
>> I did it like this in a DataDomainListener:
>>
>> @PreUpdate( { CayenneDataObject.class } )
>> public void handleBeforeUpdateHook( CayenneDataObject object ) {
>> if( object instanceof BeforeSaveHook ) {
>> ((BeforeSaveHook)object).beforeSaveAction();
>> }
>> }
>>
>> and then have BeforeSaveHook be an interface, and then implementing
>> beforeSaveAction in the DataObject classes. To get the actual changes, I
>> also didn't find anything handy, and ended up doing it like this (in my
>> custom DataObject subclass):
>>
>> public Map<String,ValueDifference<Object>> changedAttributes() {
>> Set<String> attributeKeys = new HashSet<>( attributeKeys() );
>> Map<String,Object> dataRow = oc().getObjectStore().getSnapshot(
>> getObjectId() );
>>
>> if( dataRow == null ) { // newly inserted object
>> dataRow = new HashMap<>();
>> for( String key : attributeKeys ) {
>> dataRow.put( key, null );
>> }
>> }
>>
>> Map<String,Object> committedValues = new HashMap<>();
>> Map<String,Object> uncommittedValues = new HashMap<>();
>> for( String key : dataRow.keySet() ) {
>> if( !attributeKeys.contains( key ) ) continue;
>> committedValues.put( key, dataRow.get( key ) );
>> Object uncommittedValue = readPropertyDirectly( key );
>> uncommittedValues.put( key, uncommittedValue );
>> }
>>
>> MapDifference<String,Object> difference = Maps.difference(
>> committedValues, uncommittedValues );
>> Map<String,ValueDifference<Object>> entriesDiffering =
>> difference.entriesDiffering(); // assuming the all keys will always be
>> present in both
>> return entriesDiffering;
>> }
>>
>>
>> (where ValueDifference and MapDifference are Guava classes). Hope it helps,
>> perhaps someone else has a better solution.
>>
>> Maik
>>
>>
>>
>>> Am 22.01.2019 um 17:06 schrieb Andrew Willerding <[email protected]>:
>>>
>>> I can't seem to find documentation, or better yet some examples for 4.0 or
>>> 4.1 that explains how to check for either a single property change or how
>>> to get a list of the property changes in an onPreUpdate callback. Unless
>>> I'm missing something obvious (entirely likely ;-) ) the Lifecycle events
>>> documentation doesn't seem to mention any way to do this. Is this
>>> something that I need to manually track in the application?
>>>
>>> Also, what should I do if I want to reject the changes inside of an
>>> onPreUpdate callback? Do I need to do an explicit rollback or simply throw
>>> a CayenneRuntimeException of some sort? I'm guessing it's an explicit
>>> rollback.
>>>
>>> Thanks,
>>>
>>> Andrew
>>>
>>>
>>>
>>