Friday, June 24, 2016

Caused by: org.apache.sling.api.resource.PersistenceException: Resource is not modifiable - Adobe CQ5/AEM

The below exception will be thrown most of the cases while accessing the servlet with post from AEM.

The actual issue is AEM could not ale to resolve the servlet and assumes it as a resource path but this is not a valid resource path, the below exception will be thrown when AEM tries to set the property values.

Caused by: org.apache.sling.api.resource.PersistenceException: Resource at '/services/formservlet' is not modifiable.
    at org.apache.sling.servlets.post.impl.helper.SlingPropertyValueHandler.setProperty(SlingPropertyValueHandler.java:153)
    at org.apache.sling.servlets.post.impl.operations.ModifyOperation.writeContent(ModifyOperation.java:411)
    at org.apache.sling.servlets.post.impl.operations.ModifyOperation.doRun(ModifyOperation.java:101)

The steps to narrow down the issue:

Resolve the Servlet:

Go to http://<<AEM Host>>:4503/system/console/configMgr - Sling--> Sling Servlet Resolver and resolve the servlet path, if the servlet path is resolved then there is no issue if not the servlet is not configured properly.

Path resolved to a Servlet


Path not resolved a Servlet

Verify the Servlet configuration:

Cross verify and make sure the servlet is configured properly

e.g servlet

@Component(
immediate = true,
label = "Servlet",
description = "Servlet",
metatype = true)
@SlingServlet(
name = "FormServlet",
description = "FormServlet",
methods = "POST",
generateComponent = false,
paths = "/services/formservlet")
@Service(value = Servlet.class)
public class FormServlet extends SlingAllMethodsServlet implements Serializable {

@Override
protected void doPost(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws ServletException,
IOException {
        }
protected void doGet(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws ServletException,
IOException {
doPost(request, response);
}

}

Verify the servlet resolver configuration:

Go to http://<<AEM Host>>:4503/system/console/configMgr - Sling--> Apache Sling Servlet/Script Resolver and Error Handler and make sure the servlet base patch is added under Execution paths.


Apache Sling Referrer Filter:

If the servlet is invoked externally then make sure the host name of the source system is added to the Allow Hosts section of the Apache Sling Referrer Filter


CSRF Filter(above AEM 6.1):

Adobe added CSRF (Cross-Site Request Forgery) protection with version 6.1 and we need to ensure that the CSRF token is included while submiting the form.

This should be handled automatically if we are using AEM's version of jQuery. This library has the code to get the token and add it to all XHR and forms.

If we are using a different version of jQuery or not using the jQuery, then we have to include the 'granite.csrf.standalone' client library and it will do the same functionality.

Refer the following link for more details - https://helpx.adobe.com/experience-manager/using/custom-sling-servlets6_1.html


Also, if the servlet is working properly from publisher/author and not only working from dispatcher then the issue might be with some of the cached scripts in dispatcher is not updated, try to clear the dispatcher cache for JS scripts and try the scenario again.




Wednesday, June 22, 2016

Dispatcher Cache Invalidation for Multi Site Configuration - Adobe CQ5(AEM)

This post will explain the approach to invalidate the cache for particular site in multi site configuration - Adobe CQ5(AEM).

Recently, i was working on a dispatcher caching issue with multi site configuration - The cache was not getting invalidated in all the dispatcher.

The setup is with multiple dispatcher connected via load balancer. The load balancer will route the request to individual dispatchers via round robin algorithm. The dispatcher is configured with individual virtual host and farm for every site(Load balanced DNS is used).

The flush agent was configured in publisher for every site with load balanced DNS(the flush agent was equal to number of sites configured in dispatcher) - The issue here is when ever publisher send the invalidation request that is not reaching the corresponding dispatcher as the flush agent is configured with load balanced DNS for invalidation URI - The request will be send to random dispatcher from the load balancer due to this the cache will not be invalidated in all the dispatcher.

Solution:

Create a flush agent in individual publisher that points to individual dispatcher(based on the renders configuration). The flush agent should be configured with dispatchers server name(one flush agent in one publisher)

http://dispatcher1.server.name:80/dispatcher/invalidate.cache


Make sure the following HTTP Headers are configured.


The flush agent can be configured in author also, if we are configuring in author then the number of flush agents should be equal to number of dispatchers.

Create a Location Match in all the dispatchers httpd.con file for all the websites.

<LocationMatch "^/dispatcher/invalidate.cache$">
 
    # Site Finance
    SetEnvIfNoCase CQ-Path ".*/content/sample1/.*" FLUSH_HOST=sample1.com
    RequestHeader set Host %{FLUSH_HOST}e env=FLUSH_HOST

    # Site TR
    SetEnvIfNoCase CQ-Path ".*/content/sample2/.*" FLUSH_HOST=sample2.com
    RequestHeader set Host %{FLUSH_HOST}e env=FLUSH_HOST
</LocationMatch>

Based on the CQ-Path the corresponding sites cache will be invalidated.

Referred from  - http://www.netcentric.biz/blog/2016/01/aem-dispatcher-cache-invalidation-for-multiple-dispatcher-farms.html



Monday, June 20, 2016

Query the pages with the properties of child node - Adobe CQ5/AEM

Query to find the pages with the properties of child nodes of the page


SELECT * FROM [cq:Page] AS page WHERE ISDESCENDANTNODE(page ,"<<Parent folder of pages>>")  AND [jcr:content/<<child node name>>/<<child node property>>]=<<value>>

e.g

SELECT * FROM [cq:Page] AS page WHERE ISDESCENDANTNODE(page ,"/content")  AND [jcr:content/test_node/test_property=test

http://<<AEM Host>>:<<AEM Port>>/crx/explorer/ui/search.jsp - Paste the query and click on Search Now.



Contact Form

Name

Email *

Message *