Fix wrong session user during Solr Hot reindex

Solr hot update indexing always uses current session user, for example current backoffice user, who triggered solr hot reindex. In lots of real world cases it would lead to wrong results in solr due to different flexible search restrictions, which are applied to backoffice user and solr indexing user.

Root cause is in AbstractIndexerStrategy#resolvePks().

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
protected List<PK> resolvePks() throws IndexerException {
    if (this.pks == null) {
        FlexibleSearchQuerySpec querySpec = this.createIndexerQuery();
        String userUID = querySpec.getUser();
        UserModel user = this.userService.getUserForUID(userUID);
        this.userService.setCurrentUser(user);
        String query = querySpec.getQuery();
        Map<String, Object> queryParameters = querySpec.createParameters();
        return this.executeIndexerQuery(this.facetSearchConfig, this.indexedType, query, queryParameters);
    } else {
        return this.pks;
    }
}

Method resolvePks overrides current session user from solr query to fetch products with proper flexible search restrictions, same session user would be passed into solr worker threads(DefaultIndexerStrategy#createIndexerWorker()) and in such way used in all ValueProvider and ValueResolver. But for hot update indexing we preselect products, so user from solr product fetch query would not override current session user.

To fix that behavior we need always override session user from solr query, so proper one is passed in solr indexing workers. In solr indexing workers we pass data from session and IndexerContext, so it would be a good idea to hook into IndexerContext initialization process. For that we can use
implement ExtendedIndexerListener and override afterPrepareContext method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.blog.core.search.solrfacetsearch.listeners.indexerlisteners;

import de.hybris.platform.core.model.user.UserModel;
import de.hybris.platform.servicelayer.user.UserService;
import de.hybris.platform.solrfacetsearch.config.IndexOperation;
import de.hybris.platform.solrfacetsearch.config.IndexedType;
import de.hybris.platform.solrfacetsearch.config.IndexedTypeFlexibleSearchQuery;
import de.hybris.platform.solrfacetsearch.indexer.ExtendedIndexerListener;
import de.hybris.platform.solrfacetsearch.indexer.IndexerContext;
import de.hybris.platform.solrfacetsearch.indexer.exceptions.IndexerException;
import de.hybris.platform.solrfacetsearch.indexer.exceptions.UndefinedIndexerQuery;

import javax.annotation.Resource;

public class HotUpdateIndexerListener implements ExtendedIndexerListener {

    @Resource
    private UserService userService;

    @Override
    public void afterPrepareContext(IndexerContext context) throws IndexerException {
        IndexOperation indexOperation = context.getIndexOperation();
        IndexedType indexedType = context.getIndexedType();

        String userUID = this.extractUserFromIndexQuery(indexOperation, indexedType);
        UserModel user = this.userService.getUserForUID(userUID);
        this.userService.setCurrentUser(user);
    }

    private String extractUserFromIndexQuery(IndexOperation indexOperation, IndexedType indexedType) throws IndexerException {
        IndexedTypeFlexibleSearchQuery query = indexedType.getFlexibleSearchQueries().get(indexOperation);
        if (query == null) {
            throw new UndefinedIndexerQuery(indexOperation + " query not defined in configuration.");
        } else {
            return query.getUserId();
        }
    }

    @Override
    public void beforeIndex(IndexerContext indexerContext) throws IndexerException {
        //No need to anything just before index.
    }

    @Override
    public void afterIndex(IndexerContext indexerContext) throws IndexerException {
        //No need to anything after index.
    }

    @Override
    public void afterIndexError(IndexerContext indexerContext) throws IndexerException {
        //No need to anything after index error.
    }
}

And initialize listener in spring context:

1
2
3
4
5
6

<bean id="hotUpdateIndexerListener" class="com.blog.core.search.solrfacetsearch.listeners.indexerlisteners.HotUpdateIndexerListener"/>

<bean id="hotUpdateIndexerListenerDefinition" parent="solrListenerDefinition">
<property name="listener" ref="hotUpdateIndexerListener"/>
</bean>
comments powered by Disqus