Hi Lukas,
OK, let's think this through
1. It is probably interesting to know WHY a value has been changed. So
we should probably distinguish between
1.1. external setter calls
1.2. calls to fromXXX() methods, loading values into the record
1.3. calls to refresh(), or the new refresh(Field...)
1.4. calls to the new reset() or reset(Field)
1.5. calls to the new changed() methods, which change the internal flags
1.6. calls to store(), which change the internal flags (some special
considerations may apply to batchStore)
1.7. calls to copy() (I'm not so sure what / whom to notify, though...)
The above could be distinguished using a RecordChangeType enum
2. Some change events are interesting on a Record-level (1.2, 1.3,
1.4, 1.5, 1.6, 1.7). Some clients may be interested in listening to
value-level change events, too (1.1, 1.3, 1.4, 1.5). While JavaBeans
mainly knows PropertyChangeEvents (i.e. value-level change events), I
think you may not always want to receive 20 "uncoordinated" events for
a single refresh()
Well you thought about it a lot more than I did :). For my use case I am
happy with a simple value change listener. It can get fired on any
source of the setValue call and can be fired 20 times if there are 20
fields, I don't mind, it is just to keep the UI in sync which would
require updating each field anyway.
But yes it does make sense that if you are going to add this
functionality it would be worth going the entire way and be able to
distinguish why an update occurred and also handle record level and
value level changes.
Perhaps that kind of functionality would be better in the "trigger"
system you were describing. eg. when a store() is issued, then the
trigger could fire and pass the record object, what fields were changed
and if it was being inserted or updated. It would save bloating the
Record object.
I guess for my use case I only need the functionality in the
UpdatableRecord type.
3. Since some of the event sources are not really "vetoable" on a
value-level (1.3, 1.6), I don't think that a JavaBeans
VetoableChangeSupport is generally applicable. PropertyVetoException
being a checked exception, this might be irrelevant anyway. Hence, I'm
guessing that events are fired *after* the change is made.
I guess this would be an interesting way of enforcing some validation /
constraints on a field. But probably not the best way to go around it.
It wouldn't be the place to be defining such constraints anyway. And it
doesn't really appear to anywhere else in the scope of JOOQ?
4. We would have a List<RecordChangeListener> within
org.jooq.impl.AbstractRecord (all Record implementations), as well as
a List<ValueChangeListener> within every org.jooq.impl.Value. A
RecordChangeEvent would then contain a List<ValueChangeEvent>, every
ValueChangeEvent would reference its parent RecordChangeEvent. Events
would be fired as soon as there is at least one listener in the Record
/ in at least one Value
I wonder of the memory and performance overhead that introduces?. I
guess on an initial query there are no listeners registered. And for a
large query you aren't going to register a listener on every record. In
my use case I would only want to register on an UpdatableRecord.
5. Listener types and Event types will have to be implemented in jOOQ.
JavaBeans PropertyChangeEvent is probably too general, and too much
focused on bean property changes in the context of AWT / Swing
applications
Yes I agree.
Any other points that I may have overlooked?
You seem to have thought about it pretty thoroughly. It would work for
me. I would be concerned all the extra data would have an impact on
performance and memory usage. If you load a large data set though JOOQ
into memory then all those extra bytes count...
Getting a bit off topic... The more I have been using JOOQ, the more
things I keep wanting to add to it. It is a great project. It has really
changed the architecture of my system. It eliminates a lot of the data
layer and makes it a whole lot more agile. It would be great to be able
to plug into it in all kinds of places. So for me the more extension and
plugin points the better. I still want to implement an audit trail
system, an extensive validation system and a trigger system that all
runs through JOOQ.
You made a suggestion earlier about using jooq-codegen. Maybe there
could be a way to "plug into" JOOQ by having the generated JOOQ record
objects extend from a custom class, or add hooks into a custom class.
Then extra / custom functionality could be inserted in there. I could
then "intercept" all value changes and use my own listener system that I
coded in there. I guess that is really similar to the proxy idea.
Thanks, Ryan