Issue
I had a jar from CQ 5.6 that expose several servlets. I moved the jar to new CQ 6.3 only to find out that the servlets are not ran (tested on Servlet Resolver and it answer with com.day.cq.commons.servlets.NonExistingDispatcherServlet
-- equals to 404).
I have do several checklist to narrow down this issue:
- The Jar is an OSGI bundle that have OSGI-INF metadata exposing its services - including the servlet. It is compiled under CQ 5.6 earlier.
- The Bundle (jar) is properly registered and CQ shows the exposed servlets as service.
- The Jar is installed under
apps
directory where it is included in Apache Sling Servlet/Script Resolver and Error HandlerExecution Paths
.
Is there any missing checklist to let the servlet handle the specific path defined in sling.servlet.paths
property?
Sorry for the noob question. Thank you in advance.
EDIT
Added the rough code -- i don't think you will be interested on what happens in doPost
. As it is unrelated with registering servlet to AEM 6.3.
package com.test.something;
import java.util.Iterator;
import java.io.*;
import javax.jcr.*;
import javax.servlet.ServletException;
import java.util.*;
import java.util.Date;
import java.text.*;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.*;
import java.rmi.ServerException;
import java.security.Principal;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.api.security.user.AuthorizableExistsException;
import java.security.*;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;
import org.apache.commons.codec.binary.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.jcr.api.SlingRepository;
@Component(immediate = true)
@Service
@Properties({
@Property(name = "sling.servlet.methods", value = "POST"),
@Property(name = "sling.servlet.paths", value = { "/content/test" }),
@Property(name = "service.description", value = "Test Servlet")
})
public class TestServlet extends SlingAllMethodsServlet {
@Reference
private SlingRepository repository;
protected final Logger log = LoggerFactory.getLogger("SSOLogger");
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
throws ServerException, IOException {
try {
this.doPost(request, response);
} catch (ServletException e) {
//do some logging
}
}
@Override
protected void doPost(SlingHttpServletRequest request,
SlingHttpServletResponse response)
throws ServletException, IOException {
try {
//do something
} catch (RepositoryException ex) {
//do some logging
}
}
}
And yes, this servlet is registered in OSGi Components. It states the properties correctly.
EDIT: Narrowing down the culprit it seems
@Reference
private SlingRepository repository;
does not seems to be loaded properly.. weird. It caused the component to be in Satisfied state instead of Active.
EDIT: Checking the OSGi Services in CQ, noticed that org.apache.sling.jcr.api.SlingRepository
in CQ 5.6 was provided by com.day.crx.sling.server
while in CQ 6.3 it is provided by com.adobe.granite.repository
. Not sure if it is the cause or not.
Solution
After messing a bit and checking the logs. Apparently the issue lies on the maven scr plugin that did not generate the necessary binding (bind and unbind in @Reference
) methods. Basically, i need to strictly define the method such as:
public class TestServlet extends SlingAllMethodsServlet {
@Reference(bind = "bindRepository", unbind = "unbindRepository")
private SlingRepository repository;
protected void bindRepository(SlingRepository repository){
this.repository = repository;
}
protected void unbindRepository(SlingRepository repository){
if(this.repository == repository){
this.repository = null;
}
}
}
There are several item we need to check if the Service is stuck in Satisfied state:
- Configuration, is every configuration field is configured?
- Other services that it depends to, are they already active or also in Satisfied state?
- Have you whitelisted the service ? -- if you are using
slingRepository.loginAdministrative(null)
. - Any exception happen when it was activated (denoted by
@Activate
)?
I know the checklist are incomplete, i am also still learning this OSGi thingy. It is interesting though a bit unclear (no documentation for dummies).
Answered By - Bagus Tesa