RE: onUpdate(DLFileEntry) listener !!

Vivek Mehta, modified 6 Years ago. Junior Member Posts: 48 Join Date: 4/7/19 Recent Posts
Hi all!!I am using liferay 6.2 CE. I was tracking the action of user. Everything worked fine till I reached adding file model  listener. When i am updating or creating a file then the listeners afterUpdate() and afterCreate() are working fine. But when i am downloading a file or document then also the afterUpdate() is being called. So, is there a way i can track whether i am downloading a file or updating it. Also in case of downloading, when i am using  "  GetterUtil.getLong(PrincipalThreadLocal.getName()); " to get the current user id , it is returnig 0. So, I would be glad if anyone could help me out.
thumbnail
Olaf Kock, modified 6 Years ago. Liferay Legend Posts: 6441 Join Date: 9/23/08 Recent Posts
Vivek Mehta:

when i am downloading a file or document then also the afterUpdate() is being called. So, is there a way i can track whether i am downloading a file or updating it.
Not sure if this pointer helps: I'm assuming that the update after download is caused by the view counter being incremented. If I remember correctly, this can be configured in portal-ext.properties. If you want to track downloads through a model listener, you'll need to determine if the view counter changed (this will be your pointer for a download) or if content changed.
Alternatively, if the view counter isn't incremented, I'd recommend to audit downloads from higher up the chain, e.g. through the web layer that actually handles the download. Because the ModelListener will only see changes, not access to an object.
Vivek Mehta, modified 6 Years ago. Junior Member Posts: 48 Join Date: 4/7/19 Recent Posts
Thanks Olaf,getReadCount() gets updated when we download a file. Actually previously i was implementing this in  onAfterUpdate() listener, so it was giving both old and new read count as modified. Now i used onBeforeMethod() and now I am able to get both old and new readCount and tell whether the file is being updated or downloaded. This issue is solved. But the main problem I am facing is in getting userId when I am downloading a file. It is always giving userId as 0 and throwing no such user exception. Whereas , it is workking fine when I am normally updating the file.
thumbnail
Christoph Rabel, modified 6 Years ago. Liferay Legend Posts: 1555 Join Date: 9/24/09 Recent Posts
I think, you need to implement a service wrapper for that. The listener is in a different thread than the update and the information is simply not there.
Vivek Mehta, modified 6 Years ago. Junior Member Posts: 48 Join Date: 4/7/19 Recent Posts
Hi Christoph,I used your method and tried to fetch the userId using service wrappers, but in this case also I was getting  "0" only. So I tried one way :- 
       I made global variable "globalUserId" and fetched the userId in this variable  when the user logs in. And now this global variable can be used anytime and anywhere required. But when I tried fetching this id  in the login.pre  / login.post hook it was giving the user Id of default liferay admin and not the current logged in user. So, I notice that afterUpdate() function was being called even when  the user logs in. So I tried fetching the userId in this afterUpdate(User user) model listener and it workssss just perfectly now. But, I want to know Is it ok the way I have implemented it using the model listener or it can cause issues.
thumbnail
Christoph Rabel, modified 6 Years ago. Liferay Legend Posts: 1555 Join Date: 9/24/09 Recent Posts
I don't think your approach will work. What happens if multiple user login. The global variable will only hold the id of the last user.
Are you sure that you don't get the user in the servicewrappers?
You should be able to do something like this to get the user:
ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();
// Note: Test for serviceContext == null here
long userId = serviceContext.getUserId();
Vivek Mehta, modified 6 Years ago. Junior Member Posts: 48 Join Date: 4/7/19 Recent Posts
Hi Christoph,
I am afraid you are correct. I only thought about condition when someone logs in from one system only. So i set that global variable to "0" when the user logs out. But now if different users logs in from several systems, it will surely take the last logged in user only. I need to change the code again now emoticon
Vivek Mehta, modified 6 Years ago. Junior Member Posts: 48 Join Date: 4/7/19 Recent Posts
And I am getting NULL for "serviceContext".
thumbnail
Amos Fong, modified 6 Years ago. Liferay Legend Posts: 2047 Join Date: 10/7/08 Recent Posts
I think, you need to implement a service wrapper for that. The listener is in a different thread than the update and the information is simply not there.
This isn't correct. See update(T model) in https://github.com/liferay/liferay-portal/blob/master/portal-kernel/src/com/liferay/portal/kernel/service/persistence/impl/BasePersistenceImpl.java#L524. It calls modelListener in the same thread. You should be able to even throw an exception to rollback the transaction in the modelListener.
The thread spawn off should be in incrementViewCounter by the @BufferedIncrement annotation. So to catch the original thread, you'll have to go before this which is probably getFile or getFileAsStream. But I think I'd agree with Olaf though and go up even higher in the chain to the portlet.
thumbnail
Christoph Rabel, modified 6 Years ago. Liferay Legend Posts: 1555 Join Date: 9/24/09 Recent Posts
Hah.
I didn't expect that. I was always under the assumption that the ModelListeners were "separated" and anything that happens there would not be able to affect the transaction. I am not sure, I am happy with that behavior, but it is as it is.
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hey Amos,

As I am typing this I realized that I can look at the git history on the file, but I am wondering if you know off hand when this change came into effect. I ask because I normally take the same path that Christoph suggested ... if you need the service context, use a wrapper (I mean that is not the only deciding factor, but a great "initial" vetting). With this, I would assume then that I would be able to access the ServiceContext using the ServiceContextThreadLocal in the model listener, something that previously evaluated to null because of course it was running on a separate thread where the thread local had not be initialized.

So does this mean that Service Context can actually be pulled in when working with model listeners now!? emoticon
thumbnail
Amos Fong, modified 6 Years ago. Liferay Legend Posts: 2047 Join Date: 10/7/08 Recent Posts
I think it has always been this way?
https://github.com/liferay/liferay-portal/commit/4151e0da9fc30806bcb3f81f8a15867b17228984

So does this mean that Service Context can actually be pulled in when working with model listeners now!? emoticon
I just tested in 7.2 and it's not null emoticon​​​​​​​
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
:| .. ok, I must be thinking of something else then. Maybe I was confusing it with the message listeners. At any rate, good to know that it's an option! emoticon
Vivek Mehta, modified 6 Years ago. Junior Member Posts: 48 Join Date: 4/7/19 Recent Posts
Hi,
Thanks everyone for your help.I solved this issue using the doFilter () method emoticon  doFilter() method will get called very first when we download a file and from there i am sending the userId of the user through the jsonws emoticon