servletsosgiaemsling

Sling Servlet in CQ - Resource is not modifiable


I'm having some issues with a Sling Servlet in CQ. While requesting the servlet I'm getting an exception saying

Caused by: org.apache.sling.api.resource.PersistenceException: Resource at '/bin/feedServlet' 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)

In the servlet, I'm trying to inject 2 services using the @Reference annotation.

Please give me some pointers to solve this issue. Please find my Servlet code below (not complete):

@Component(immediate = true, metatype = false, label = "feedServlet")
@Service(Servlet.class)
@Properties(value = { @org.apache.felix.scr.annotations.Property(name = "sling.servlet.methods", value = "POST"),
@org.apache.felix.scr.annotations.Property(name = "sling.servlet.paths", value = "/bin/feedServlet") })
public class FeedServlet extends SlingAllMethodsServlet {
        private static final long serialVersionUID = -2139716879248038562L;
         @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY, policy = ReferencePolicy.STATIC)
         private ContentSearchService searchService;

         @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY, policy = ReferencePolicy.STATIC)
         private FeedGeneratorService feedService;

        @Override
        protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServerException,
                IOException {
             ResourceResolver resourceResolver = request.getResourceResolver();
             List<Hit> list = null;
             String feed = null;
            try {
             list = search(request, searchService);
             feed = feedService.generateFeed(list, resourceResolver);
             } catch (Throwable e) {
             }
            response.getWriter().write(feed);
        }

Note: Without these services the servlet is working fine now(previous thread). Is this an issue with the dependency injection? The serviceComponets.xml for this bundle defines these services as:

<scr:component enabled="true" immediate="true" name="com.acme.wcm.cq.servlet.FeedServlet">
        <implementation class="com.acme.wcm.cq.servlet.FeedServlet"/>
        <service servicefactory="false">
            <provide interface="javax.servlet.Servlet"/>
        </service>
        <property name="sling.servlet.methods" type="String" value="POST"/>
        <property name="sling.servlet.paths" type="String" value="/bin/feedServlet"/>
        <property name="service.pid" value="com.acme.wcm.cq.servlet.FeedServlet"/>
        <reference name="searchService" interface="com.acme.wcm.cq.search.ContentSearchService" cardinality="1..1" policy="static" bind="bindSearchService" unbind="unbindSearchService"/>
        <reference name="feedService" interface="com.acme.wcm.cq.feed.FeedGeneratorService" cardinality="1..1" policy="static" bind="bindFeedService" unbind="unbindFeedService"/>
    </scr:component>

Solution

  • I think the POST request you made wasn't handled by your servlet.

    Look the code of SlingProprtyValueHandler: src of SlingProprtyValueHandler

    CQ doesn't use your servlet, so it thinks at "/bin/feedServlet" there is a resource and it tries to modify it (because it is a POST request), but there is not any resource, that's why you got an exception.

    Please create a doGet method for your serlvet and try to make a get request, I am sure that it won't work.

    Check your servlet is active or not under /system/console/components.

    You can also check whether the /bin path is allowed or not under /system/console/configMgr/ check "Apache Sling Servlet/Script Resolver and Error Handler".

    I hope this helps!

    p.s. It is better to map your servlet to a resource instead of a path. example code here how to map a servlet to a resource

    So you can create a a path like /etc/myApp/services and under this path you can create a myService node with a type like etc/myApp/services/myService, and you can map your servlet to this resource type.