I am trying to implement an audit trail functionality for my web application that records:
- lastModified (timestamp)
- modifiedBy (user information)
- userComment (reason for value change)
for each of my input fields (input fields are spread over several forms with different backing beans and different valueHolder classes).
The first two (lastModified and modifiedBy) are easily done with the help of an JPA AuditListener and @PrePersit and @PreUpdate methods.
The third one is a bit tricky since it requires user interaction. Best would be a dialog that asks for the user comment.
So there are (at least) two open issues: Can I establish a “global” valueChangeListener for all input fields in my application? Is this possible without attaching <f:valueChangeListener> to each single input component? Second: How can I grab the user comment. My idea is to put a p:dialog in my web page template but this dialog needs to know from which input component it is called.
Yes, with a
SystemEventListenerwhich get executed duringPreRenderViewEvent. You need to walk through the component tree as obtained byFacesContext#getViewRoot()to find all components which are aninstanceofEditableValueHolder(or something more finer-grained) and then add thenew YourValueChangeListener()by theaddValueChangeListener()method. See also this answer how to register the system event listener: How to apply a JSF2 phaselistener after viewroot gets built?You could in
YourValueChangeListener#processValueChange()set the component in question as a property of some request or view scoped which you grab byevaluateExpressionGet().It will execute the EL and auto-create the bean in its scope if necessary. The bean in turn should also hold the property representing the user comment. Finally, you can use it in your
<p:dialog>.