cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

[y6.2] Backoffice: Enriching the session with custom attributes as soon as a backoffice user logs in

Former Member
0 Kudos
1,655

Whenever a backoffice user logs in, I would like to enrich their session with custom name/value-mappings (which I later would like to use within a Flexible Search query).

To be more precise, I have created a relationship between PointOfService and Employee. The relationship defines which point of services an employee is allowed to manage. My approach is to accumulate all point of services (POS) that are assigned to the employee as soon as they log in into backoffice. I would store the POS's PKs into the session and then add a Personalization rule that restricts the employee to the previously collected POSs.

My aim is to achieve this without modifying any stock code, that means I would like to rely solely on the features the Spring framework offers (Dependency injection, AOP) in order to keep my application modular and maintainable.

What I have done so far

1. Overriding behavior with beans/aliases

I found that the method(s) [Backoffice|ResetConfiguration]AuthenticationSuccessHandler.onAuthenticationSuccess() are being called whenever a user logs in into backoffice. The instantiation is configured in backoffice/web/webroot/WEB-INF/lib/backoffice-core-[...].jar/META-INF/backoffice-core-spring-security.xml. My first approach was to inject my code by overriding the [backoffice|resetConfiguration]AuthenticationSuccessHandler beans.

However, as others have already reported I am unable to override the beans' definitions within my own custombackoffice-backoffice-spring.xml; related topics below:

I strongly assume that the problem lies in the processing sequence: My bean/alias definition would have to be processed after the original bean definition and before their actual usage in <form-login [...] authentication-success-handler-ref="backofficeAuthenticationDetailsSource" [...]> within the stock backoffice-spring-security.xml. I guess that the regular process of merging spring.xml files across all defined extensions does not apply in this context.

2. Using Spring AOP

Since I prefer not to touch any hybris stock code / configuration, my second approach was to use AOP to solve my problem. Within my custom backoffice-related extension custombackoffice, I implemented an aspect that shall react to calls to com.hybris.cockpitng.util.web.authorization.BackofficeAuthenticationSuccessHandler.onAuthenticationSuccess:

 package my;
 // ...
 @Aspect
 public class MyAspect {
     private UserService userService;
 
     @Around("execution(void com.hybris.cockpitng.util.web.authorization.ResetConfigurationAuthenticationSuccessHandler.onAuthenticationSuccess(..)) && args(request, response, authentication)")
     public void myAdvice(ProceedingJoinPoint jp, HttpServletRequest req, HttpServletResponse res, final Authentication auth) throws Throwable {
         // ...
         jp.proceed();
         // ...
         EmployeeModel u = userService.getUserForUID(auth.getName(),
                 EmployeeModel.class); // #FAILING LINE#
         // ...
         request.getSession().setAttribute(...);
     }
 }

I configured AOP by creating an aop.xml configuration file in custombackoffice/resources/META-INF

 <aspectj>
   <weaver options="-showWeaveInfo -verbose">
     <include within="com.hybris.cockpitng.util.web.authorization..*" />
     <include within="my..*" />
   </weaver>
   <aspects>
      <aspect name="my.MyAspect" />
   </aspects>
 </aspectj>

and configured the aspect's bean in custombackoffice/resources/custombackoffice-spring.xml:

 <bean id="myAspect" class="my.MyAspect" factory-method="aspectOf">
     <property name="userService" ref="userService" />
 </bean>

However, when I let this configuration run I receive an exception:

 java.lang.NullPointerException
         at de.hybris.platform.servicelayer.session.impl.DefaultSessionService.executeInLocalView(DefaultSessionService.java:94)
         at de.hybris.platform.servicelayer.search.impl.DefaultFlexibleSearchService.getJaloResult(DefaultFlexibleSearchService.java:396)
         at de.hybris.platform.servicelayer.search.impl.DefaultFlexibleSearchService.search(DefaultFlexibleSearchService.java:168)
         at de.hybris.platform.servicelayer.internal.dao.DefaultGenericDao.find(DefaultGenericDao.java:53)
         at de.hybris.platform.servicelayer.user.daos.impl.DefaultUserDao.findUserByUID(DefaultUserDao.java:36)
         at de.hybris.platform.servicelayer.user.impl.DefaultUserService.getUserForUID(DefaultUserService.java:90)
         at de.hybris.platform.servicelayer.user.impl.DefaultUserService.getUserForUID(DefaultUserService.java:103)
         at my.MyAspect.aspect(MyAspect.java:#FAILING LINE#)

The exception happens on the userService.getUserForUID line due to DefaultSessionService.getOrCreateCurrentJaloSession() returning null. While investigating this issue I found that services (including userService) perform their operation on the junit tenant while my advice runs. Their field AbstractService.currentTenant holds a reference to the junit tenant.

I then took a closer look on the server starting procedure which delivers following log (excerpt):

 [PlatformInPlaceClassLoader@462b582b] info AspectJ Weaver Version 1.8.5 built on Thursday Jan 29, 2015 at 01:03:58 GMT
 [...]
 [PlatformInPlaceClassLoader@462b582b] info using configuration /C:/y-6.2/hybris/bin/custom/custombackoffice/resources/META-INF/aop.xml
 [...]
 [PlatformInPlaceClassLoader@462b582b] info register aspect my.MyAspect
 [...]
 [32mINFO  [localhost-startStop-1] [TenantActivationAspect] Configured tenant <<master>> for aspect
 [...]
 [InnerLoader@3ced5597] info register aspect my.MyAspect
 [32mINFO  [localhost-startStop-1] (junit) [TenantActivationAspect] Configured tenant <<junit>>[327654167] for aspect

Noticeably, my aspect is being registered for both the master and junit tenant. My initial guess was that the advice is executed twice (one time for "master", the second time for "junit") but this is not the case. The advice is only executed in the junit tenant context.

Furthermore, I forced the hybris server to start without the junit tenant activated. I thus added

 installed.tenants=

to my config/local.properties configuration. This works!

3. Solving the problem with a different approach

Right now, I am going to tackle the problem by supplying overriden versions of the Default[User|Session]Service services since this approach looks more promising and controllable to me.

However, I am still curious on how to successfully pursue my two initial approaches:

  1. Is it possible to override beans that are referenced by the stock backoffice-spring-security.xml only by means of Spring's dependency injection (that means without actually touching it)?

  2. What is the deal with backoffice aspects? Why is the JUnit tenant being used instead of the master tenant? Could this actually be a bug?

View Entire Topic
pooja1_
Explorer
0 Kudos

Hi,

Please move your java file (custom file that extends backofficeAuthenticationSuccessHandler) in backoffice content i.e customBackoffice/backoffice/src folder. It should not be inside customBackoffice/src folder.

It worked for me. I was supposed to capture last login time of employee while he/she login into backoffice.

0 Kudos

Hi Pooja,

Can you share what needs to be configure in xml file for this custom Handler ?