Is Modifiable Request Context Provider available in v13?

I’m in the process of porting our 12.6.7 code to 13.4.0 (Developer Edition).

In v12 we use HstQueryManager to search documents and build a report from within the CMS in preview mode only (Channel Manager).

org.hippoecm.hst.container.ModifiableRequestContextProvider is used to set the request context to null before executing the query, and then restoring the request context afterwards. This is done to ensure the query isn’t executed within the context of the preview user (@hippo:availability=‘preview’).

It however seems in v13 that ModifiableRequestContextProvider is protected, so the existing code does not work. How would I be able to achieve the same in v13?

Here is a snippet of the v12 code to illustrate what we are doing:

... [create hstQuery and apply filtering]

final HstRequestContext ctx = RequestContextProvider.get();

ModifiableRequestContextProvider.set(null);

final HstQueryResult result = hstQuery.execute();

ModifiableRequestContextProvider.set(ctx);

request.setAttribute("result", result);

...

andre
December 3

I’m in the process of porting our 12.6.7 code to 13.4.0 (Developer Edition).

In v12 we use HstQueryManager to search documents and build a report from within the CMS in preview mode only (Channel Manager).

org.hippoecm.hst.container.ModifiableRequestContextProvider is used to set the request context to null before executing the query, and then restoring the request context afterwards. This is done to ensure the query isn’t executed within the context of the preview user (@hippo:availability=‘preview’).

In the Channel Manager the context of the ‘preview user + logged in
cms user’ is actually used, see [1]. The
ModifiableRequestContextProvider was never an api IIRC. In version 13,
it is not possible to reach it unless you really want to hack it by
creating your own ‘ModifiableRequestContextProvider’ in a package
org.hippoecm.hst.container which we do in the HST for test purposes
only, see ModifiableRequestContextProvider in hst-mock.

But as said, it is not the preview user context, and when you use the
ModifiableRequestContextProvider you are really on your own since it
is not a publicly supported feature

HTH,

Regards Ard

[1] Experience Manager Preview With Security Delegation - Bloomreach Experience Manager (PaaS/Self-Hosted) - The Fast and Flexible Headless CMS

Thanks for the info. I’d prefer not to hack anything, as that seems what may have been done with our v12 code and now causing problems. I’d rather find a “supported” way to rework the code.

If I run the v12 code as is, the query being executed is:

//element(*,myapp:package)[(@hippo:paths='c8266467-a207-44f4-b879-49b0179342a8') and not(@jcr:primaryType='nt:frozenNode') and ((@hippostd:state = 'published') and (@hippo:availability != 'live' or (@myapp:expiry_date____day <= xs:dateTime('2019-12-03T00:00:00.000+02:00'))))] order by @jcr:score descending

This brings back many results, as expected.

If I however remove setting null on ModifiableRequestContextProvider before executing, the query being executed is:

//element(*,myapp:package)[(@hippo:paths='c8266467-a207-44f4-b879-49b0179342a8') and (@hippo:availability='preview') and not(@jcr:primaryType='nt:frozenNode') and ((@hippostd:state = 'published') and (@hippo:availability != 'live' or (@myapp:expiry_date____day <= xs:dateTime('2019-12-03T00:00:00.000+02:00'))))] order by @jcr:score descending

This now returns no results, which is wrong. I believe this is as a result of and (@hippo:availability='preview') that is now part of the query, possibly because this is done inside the Channel Manager, as that is the only difference I can spot? Honestly though, I don’t really understand how availability=‘preview’ is affecting the results.

((@hippostd:state = 'published') and (@hippo:availability != 'live' or (@myapp:expiry_date____day <= xs:dateTime('2019-12-03T00:00:00.000+02:00')))) are the filters we apply, since we are looking for a list of all documents of type “package”, that are published (state) and either not live (availability) or with an “expiry_date” document property value that is in the past.

Would rewriting our code from Legacy search to Fluent search make any difference to the issue?

Perhaps the full method might help point to a better way to achieve our goal?

protected void processReportQuery(HstRequest request, HstResponse response, EssentialsListComponentInfo paramInfo) {

    final ComponentManager mngr = HstServices.getComponentManager();
    final Credentials configCred = mngr.getComponent(Credentials.class.getName() + ".hstconfigreader");
    final Repository repository = mngr.getComponent(Repository.class.getName());
	final ContentBeansTool cbt = mngr.getComponent(ContentBeansTool.class.getName());
	
    try {

		final Session mySession = repository.login(configCred);
		final Node rootNode = mySession.getNode("/content/documents/myapp");
		final HstQueryManager queryManager = cbt.createQueryManager(mySession);
        final HstQuery hstQuery = queryManager.createQuery(rootNode, (Class<? extends HippoBean>) Package.class, true);
        final Filter finalFilter = hstQuery.createFilter(); 
		final Filter filter = hstQuery.createFilter();
		
        hstQuery.setFilter(finalFilter);

        filter.addNotEqualTo("hippo:availability", "live");
        final Filter subFilter = hstQuery.createFilter();
        subFilter.addLessOrEqualThan("myapp:expiry_date", Calendar.getInstance(), DateTools.Resolution.DAY);
        filter.addOrFilter(subFilter);
        
		final Filter stateFilter = hstQuery.createFilter();
		
        stateFilter.addEqualTo("hippostd:state", "published");

        finalFilter.addAndFilter(stateFilter);
        finalFilter.addAndFilter(filter);
        
        // final HstRequestContext ctx = RequestContextProvider.get();

        // ModifiableRequestContextProvider.set(null);

        log.debug("Query String: {}", hstQuery.getQueryAsString(false));
        final HstQueryResult result = hstQuery.execute();

        // ModifiableRequestContextProvider.set(ctx);

        request.setAttribute("result", result);
        
        dumpResults(result);

        final Pageable<? extends HippoBean> pageable;
        pageable = getPageableFactory().createPageable(
                    result.getHippoBeans(),
                    result.getTotalSize(),
                    result.getTotalSize(),
                    0);
 
        populateRequest(request, paramInfo, pageable);

		
	} catch (LoginException e1) {
		log.error("Failed to log into repository with credentials {}",configCred,e1);
	} catch (RepositoryException e1) {
		log.error("Failed to get repository session ",e1);
	} catch (IllegalStateException e) {
		log.error("State is all wrong ",e);
	} catch (QueryException e) {
		log.error("Query issue ",e);
	}
    
}

Hey Andre,

can you otherwise explain in words what you’d like to achieve? Something like : an overview of all preview documents readable for user X

Regards Ard

We have a “package” document type (Package.class / myapp:package), which has an expiry date property (myapp:expiry_date), which is when the price displayed on the “package” is valid until. This is different to the (scheduled) unpublish date, as a “package” can still be displayed to an internet user, but the price on it is not valid anymore, and needs to be reviewed.

So our CMS users (editor / author) logs into the CMS and goes to a page that runs the search query, and lists all documents of type “package”, that have previously been published to internet users (NOT preview) and either not live anymore (manually or scheduled unpublished) OR still live with an “expiry_date” that is in the past.

They can then edit and review the documents in the result set.

When I say I want the documents that have previously been published to internet users, NOT preview, I mean the one with the green icon or [3] in the document path, not the blue one:

image

Even if I simplify the code by removing all filters, which I expect would give me all documents of type “package”, the query being executed is finding all “preview” documents, not “live” documents that I’m after:

//element(*,travelcms2:package)[(@hippo:paths='aa4f1e01-d050-463d-b0cd-efc23e16ec11') and (@hippo:availability='preview') and not(@jcr:primaryType='nt:frozenNode')] order by @jcr:score descending

(@hippo:availability=‘preview’) is the part of the query that is wrong, but I’m not adding it, so my guess is it is from the request context.

protected void processReportQuery(HstRequest request, HstResponse response, EssentialsListComponentInfo paramInfo) {

    final ComponentManager mngr = HstServices.getComponentManager();
    final Credentials configCred = mngr.getComponent(Credentials.class.getName() + ".hstconfigreader");
    final Repository repository = mngr.getComponent(Repository.class.getName());
    final ContentBeansTool cbt = mngr.getComponent(ContentBeansTool.class.getName());
    
    try {

        final Session mySession = repository.login(configCred);
        final Node rootNode = mySession.getNode("/content/documents/myapp");
        final HstQueryManager queryManager = cbt.createQueryManager(mySession);
        final HstQuery hstQuery = queryManager.createQuery(rootNode, (Class<? extends HippoBean>) Package.class, true);
       
        log.debug("Query String: {}", hstQuery.getQueryAsString(false));

        final HstQueryResult result = hstQuery.execute();

        request.setAttribute("result", result);
        
        dumpResults(result);

        final Pageable<? extends HippoBean> pageable;
        pageable = getPageableFactory().createPageable(
                    result.getHippoBeans(),
                    result.getTotalSize(),
                    result.getTotalSize(),
                    0);

        populateRequest(request, paramInfo, pageable);

        
    } catch (LoginException e1) {
        log.error("Failed to log into repository with credentials {}",configCred,e1);
    } catch (RepositoryException e1) {
        log.error("Failed to get repository session ",e1);
    } catch (IllegalStateException e) {
        log.error("State is all wrong ",e);
    } catch (QueryException e) {
        log.error("Query issue ",e);
    }
    
}

It seems that using “hippostd:stateSummary” and filtering for “changed” or “live” might actually give me the results I’m after (instead of availability and state). That way it seems irrelevant whether I’m finding the preview (blue icon) or the live (green icon) document. I will test this with proper data to see if I can use it.

Hi Andre,

The part (@hippo:availability=‘preview’) is added by the context
indeed. This is because you are using an HST query via
HstQueryManager. Just don’t use the HstQueryManager but query JCR
directly with ‘mySession’. You can use

mySession.getWorkspace().getQueryManager().createQuery(query, “xpath”).execute()

After that, use
org.hippoecm.hst.content.beans.manager.ObjectConverter#getObject(javax.jcr.Node)
to transform the resulting nodes into HippoBean instances

HTH,

Regards Ard

1 Like

Thank you, I will try this