Recently, for one of our Liferay implementations, we ran into an issue in production wherein users would randomly lose an organization role that they were assigned. It was relatively rare and no steps to reproduce the problem were provided.

We didn’t know if the issue existed in OOTB Liferay code or any of the customizations done in this client’s implementation. We knew which Liferay code updates the user roles but we didn’t know how and who is calling it. At this time I felt a need for a caller-id like our cell phone that can tell us who is calling this Liferay user role update method. We didn’t update any Liferay code for this implementation and I wanted to keep it that way.

After some thinking I found a way for my Caller-Id implementation. Liferay uses Spring for its service injection and I decided to use Springs AOP for caller-id.

In AOP you define a class which is an aspect. You also define point cut (java methods) for which you want to apply your aspect. Anytime the point cut method is called your aspect is called as well.

Below is what I did.

First I added my aspect as a bean as below.

<bean id=”userRoleLoggingAspect” class=”com……portal.util.LoggingAspect”/>

Then I added aspect declaration. Here, I wanted my aspect to work on UserLocalServiceImpl.unsetRoleUsers and UserServiceImpl.unsetRoleUsers methods.

<aop:config>
<!– The Advice(s). –>

<aop:aspect id=”loggingAspect” ref=”userRoleLoggingAspect”>
<aop:before pointcut=”execution(* com.liferay.portal.service.impl.UserLocalServiceImpl.unsetRoleUsers(long, long[]))” method=”logEntryUnsetRoleUsersArray”/>
<aop:before pointcut=”execution(* com.liferay.portal.service.impl.UserServiceImpl.unsetRoleUsers(long, long[]))” method=”logEntryUnsetRoleUsersArray”/>
</aop:aspect>
</aop:config>

Here is what I had in my java file.

public class LoggingAspect {
private static final Logger logger = Logger.getLogger(LoggingAspect.class);
 public void logEntryUnsetRoleUsersArray(JoinPoint joinPoint) {
try {
 throw new Exception(“unset role called”);
} catch (Exception e) {
logger.debug(e); //e.printStackTrace();
}
}
}

That’s how simple it was. I deployed this on a dev server and tested that it was working. I manually set/unset some roles and verified that my caller-id was captured in the logs. Of course we can add more stuff to capture in the aspect class.

This type of aspect-based caller-id approach can be very useful in debugging critical issues in a production environment without requiring you to modify any Liferay code. Obviously, I showed a very specific use of Caller-Id, but this can be extrapolated to a variety of third-party software.