Hello,
I'm a Java intern and I've been assigned to make a servlet that receives a get request and returns a random number in response. I've already done a project before that submitted a form request to register new partners using a model I've created. Nevertheless, I've been requested to make this one without creating a new component.
This is my service:
@component(service = {RandomNumberServiceImpl.class}, immediate = true)
public class RandomNumberServiceImpl implements RamdomNumberService {
@reference
private Resource resource;
public int generateRandomNumber() {
return (int) (Math.random () * 100);
}
}
And this is my servlet:
@component(service = Servlet.class,
property = {
"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.paths=" + "/bin/random-number",
"sling.servlet.selectors=" + "json"})
public class RandomNumberServlet extends SlingAllMethodsServlet {
private static final Logger log = LoggerFactory.getLogger (RandomNumberServlet.class);
@reference
private RamdomNumberService ramdomNumberService;
protected void doGet(SlingHttpServletRequest req, SlingHttpServletResponse resp) throws ServletException, IOException {
JSONObject responseObject = new JSONObject();
try {
int randomNumber = ramdomNumberService.generateRandomNumber ();
responseObject.put("randomNumber", randomNumber);
resp.setContentType("application/json");
resp.getWriter().write(responseObject.toString());
} catch (Exception e) {
log.error("Error generating random number: {}", e.getMessage());
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error generating random number");
}
}
}
But whenever I try to make the get request on the author instance (localhost:port/bin/random-number, localhost:port/bin/random-number.json etc) I always get a 404 no resource found error. I've already checked if /bin is permitted in the system console. What am I missing? Is it because I didn't create a model/component and don't have a resource for it in JCR? How can I make this work?
Solved! Go to Solution.
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
Clean-up code:
It seems that you don't need following in your service. PLease remove this. The @Reference will work for a Sling Model, because Sling Model is instantiated in context of a resource. The same would not work for stand-alone services.
@reference
private Resource resource;
Assure servlet and service are active
Step-1: Assure that your Servlet is Active.
Step-2: Incase, it isn't active. Click on the component.
Repeat same steps for your Service also.
Clean-up code:
It seems that you don't need following in your service. PLease remove this. The @Reference will work for a Sling Model, because Sling Model is instantiated in context of a resource. The same would not work for stand-alone services.
@reference
private Resource resource;
Assure servlet and service are active
Step-1: Assure that your Servlet is Active.
Step-2: Incase, it isn't active. Click on the component.
Repeat same steps for your Service also.
Very nice, thank you! When I did what you asked, I got into the wknd bundle I'm using for this project it showed that the bundle last modification was a month ago, even though I was using "mvn clean install -P autoInstallSinglePackage" in my IDE (Intellij). Do I need to manually update the bundle constantly?
P.S: now I have another problem. I'm supposed to publish it and be able to run it through dispatcher returning the same answer using cached memory. When I try to access the servlet through publish I get the same error as before (404 no resource found), although I can see published pages. Do I need to publish the servlet in order for it to work? How can I do it?
Is the WKND package used as a dependency? Or are we making changes to WKND bundle?
"autoInstallSinglePackage" is for Packages like ui.apps / ui.config etc.
For the new questions, which differ from the original post, I request you to create separate questions. It helps you, advisors and anyone referring the post in future.
Regarding dispatcher query:
We do not publish servlets. They are deployed via mvn commands to publish. Verify the servlet on publish, once its deployed
On dispatcher, you would need to allow access to this servlet via filters section. By default, everything is blocked and then servlet/pages are explicitly allowed on dispatcher.
# Allow specific URLs
/002-allow-random-number { /type "allow" /url "/bin/random-number" }
If something like this is already allowed, then your Servlet should also be accessible.
/005 { /type "allow" /url "/bin/*" } # allow bin path access
Also, please consider the code clean-ups as suggested by other advisors
RandomNumberService service is not annotated correctly. You need to update it from Impl to Interface in the @component annotation
@component(service = {RandomNumberService.class}, immediate = true)
Additionally, you can remove the following code block as it is not required
@reference
private Resource resource;
However, note that the annotations should use uppercase "C" and "R" for Component and Reference, respectively.
HI @RafaelSp ,
Try to make below changes in your code:
1. In your service class add below
@component(service = {RandomNumberService.class}, immediate = true)
2. Remove "resource" object from your service class if you need the resource then get it through ResourceResolverFactory or from the request.getResourceResolver() passed from servlet.
3. In servlet make following changes, however not mandatory:
public class RandomNumberServlet extends SlingSafeMethodsServlet {
4. In servlet
@Reference
private RamdomNumberService ramdomNumberService;
Thanks
Tarun
You can try this
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.service.component.annotations.Component;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Random;
@Component(immediate = true, service = MyRandomServlet.class,
property = {
"sling.servlet.methods=GET",
"sling.servlet.paths=/bin/random"
})
public class MyRandomServlet extends SlingSafeMethodsServlet {
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
// Generate a random number
int randomNumber = new Random().nextInt(1000);
// Set the response content type
response.setContentType("text/plain");
// Write the random number to the response
response.getWriter().write(String.valueOf(randomNumber));
}
}
I see that in your @Component properties declaration, I think instead of
sling.servlet.extensions=" + "json"
you are using
"sling.servlet.selectors=" + "json"
Please change the declaration to "sling.servlet.extensions" and give it a try.