Hi Andrus Thanks for your help. Here are logs with thread names as well. I logged in in Thread 24 and created 5 new records. AuditListener is running in different threads. I am running this in Eclipse 4.3.2 with the RunJettyRun plugin running Jetty 8.1.2. Log statement is
logger.info("Thread " + t.getId() + " " + t.getName() + " Looking for TblPerson
" + idUser);
//where t = Thread.currentThread()
2014-08-02 09:37:30,563 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 setTheUserId 220
2014-08-02 09:38:14,064 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 Looking for TblPerson 220
2014-08-02 09:38:14,064 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 Looking for TblPerson 220
2014-08-02 09:38:14,064 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 Looking for TblPerson 220
2014-08-02 09:38:14,065 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 Looking for TblPerson 220
2014-08-02 09:38:31,045 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 23
qtp1248572294-23 idUser == null
2014-08-02 09:38:31,045 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 23
qtp1248572294-23 idUser == null
2014-08-02 09:38:31,045 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 23
qtp1248572294-23 idUser == null
2014-08-02 09:38:31,046 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 23
qtp1248572294-23 idUser == null
2014-08-02 09:38:57,932 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 19
qtp1248572294-19 idUser == null
2014-08-02 09:38:57,932 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 19
qtp1248572294-19 idUser == null
2014-08-02 09:38:57,932 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 19
qtp1248572294-19 idUser == null
2014-08-02 09:38:57,933 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 19
qtp1248572294-19 idUser == null
2014-08-02 09:39:16,048 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 23
qtp1248572294-23 idUser == null
2014-08-02 09:39:16,048 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 23
qtp1248572294-23 idUser == null
2014-08-02 09:39:16,048 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 23
qtp1248572294-23 idUser == null
2014-08-02 09:39:16,048 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 23
qtp1248572294-23 idUser == null
2014-08-02 09:39:41,670 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 Looking for TblPerson 220
2014-08-02 09:39:41,670 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 Looking for TblPerson 220
2014-08-02 09:39:41,670 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 Looking for TblPerson 220
2014-08-02 09:39:41,670 INFO
[au.com.tramanco.chekway.cayenne.audit.AuditListener] Thread 24
qtp1248572294-24 Looking for TblPerson 220
Maybe the request is running in a different thread each time. I will do some
more checking.
Tim
On 1 Aug 2014, at 23:22, Andrus Adamchik <[email protected]> wrote:
> Hi Tim,
>
> Yes you are going in the right direction with AuditableProcessor.
>
>> If I save the user in a ThreadLocal in the data channel filter object, I get
>> a different user each time (often blank) because the data channel filter
>> seem to run in its own thread which changes each time.
>
> This seems suspect. In a typical web app, all processing happens in request
> thread. Cayenne listeners are processed in the same thread as ObjectContext
> commit, which is normally your request thread. Could you possibly print
> thread names from within setTheUserId and doPrePersist methods ? Maybe that
> will give you a hint. Request threads in Tomcat and Jetty have easily
> identifiable names.
>
> Andrus
>
>
> On Jul 20, 2014, at 2:23 AM, D Tim Cummings <[email protected]> wrote:
>
>> Hi all
>>
>> I want to set up a simple audit trail which basically links who was the
>> person to create a record to that record. I am using Cayenne 3.2M1 and
>> Tapestry 5.3.7. I figure I need to set up a data channel filter to catch
>> changes to that record and then save a link to the user who made the change.
>>
>> The problem is, if I save the user in the data channel filter object when
>> someone logs in, then all created records link to the last logged in user.
>>
>> If I save the user in a ThreadLocal in the data channel filter object, I get
>> a different user each time (often blank) because the data channel filter
>> seem to run in its own thread which changes each time.
>>
>> I have been watching the excellent and now freely available podcast by
>> Andrus Adamchik presented to WebObjects developers "Advanced Apache Cayenne"
>> where he talks about lifecycle events, (callbacks, listeners), caching, data
>> channel filters, clustering, in cayenne 3.2M1.
>> https://itunes.apple.com/podcast/webobjects-podcasts/id270165303?mt=2#
>> In Andrus's sample code he uses AuditableProcessor, but I couldn't think how
>> to use it to solve this problem.
>>
>> Here is a copy of my listener/data channel filter with the ThreadLocal code.
>>
>> Thanks
>>
>> Tim
>>
>>
>> public class AuditListener implements DataChannelFilter {
>>
>> private static final Logger logger =
>> LoggerFactory.getLogger(AuditListener.class);
>>
>> private ThreadLocal<Integer> tlUserId;
>>
>> @PrePersist(entityAnnotations=TagCreateCancel.class)
>> void doPrePersist(DataObject object) {
>> if ( object instanceof AuditableCreateCancel ) {
>> AuditableCreateCancel acc = (AuditableCreateCancel) object;
>> TblPerson user = getTheUser(object.getObjectContext());
>> acc.setTblPersonCreate(user);
>> }
>> }
>>
>> private TblPerson getTheUser(ObjectContext oc) {
>> Thread t = Thread.currentThread();
>> Integer idUser = tlUserId.get();
>> if ( idUser == null ) {
>> logger.info("Thread " + t.getId() + " idUser == null ");
>> return null;
>> }
>> logger.info("Thread " + t.getId() + " Looking for TblPerson " + idUser);
>> TblPerson p = Cayenne.objectForPK(oc, TblPerson.class, idUser.intValue());
>> return p;
>> }
>>
>> @Override
>> public void init(DataChannel channel) {
>> tlUserId = new ThreadLocal<Integer>();
>> }
>>
>> @Override
>> public QueryResponse onQuery(ObjectContext originatingContext, Query query,
>> DataChannelFilterChain filterChain) {
>> return filterChain.onQuery(originatingContext, query);
>> }
>>
>> @Override
>> public GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes,
>> int syncType, DataChannelFilterChain filterChain) {
>> try {
>> return filterChain.onSync(originatingContext, changes, syncType);
>> } finally {
>> //
>> }
>> }
>>
>> public void setTheUserId(int idUser) {
>> Thread t = Thread.currentThread();
>> logger.info("Thread " + t.getId() + " setTheUserId " + idUser);
>> tlUserId.set(Integer.valueOf(idUser));
>> }
>>
>> }
>>
>
signature.asc
Description: Message signed with OpenPGP using GPGMail
