Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

Java Random Number Get Servlet

Avatar

Level 2

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? 

 

 

 

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

@RafaelSp 

 

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.

aanchalsikka_0-1699856808356.png

 

Step-2: Incase, it isn't active. Click on the component.

  • On the next page, it would show you which dependency is unsatisfied.

 

Repeat same steps for your Service also. 

 


Aanchal Sikka

View solution in original post

7 Replies

Avatar

Correct answer by
Community Advisor

@RafaelSp 

 

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.

aanchalsikka_0-1699856808356.png

 

Step-2: Incase, it isn't active. Click on the component.

  • On the next page, it would show you which dependency is unsatisfied.

 

Repeat same steps for your Service also. 

 


Aanchal Sikka

Avatar

Level 2

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?

Avatar

Community Advisor

@RafaelSp 

 

Is the WKND package used as a dependency? Or are we making changes to WKND bundle?

 

  • If its a dependency, we need not install again. An active bundle is enough
  • If we are making changes in bundle, it can be deployed in 2 ways:
    • Bundle only: In this case, go the bundle folder and execute mvn clean install -PautoInstallBundle 
    • Entire project: Then go to the project folder and execute mvn clean install -PautoInstallPackage

 

"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.

  • Advisors can quickly check description and respond
  • You will get attention from all advisors on new query
  • For anyone referring in future, the related info is in one place and organized manner.


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


Aanchal Sikka

Avatar

Community Advisor

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.

Avatar

Community Advisor

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

Avatar

Community Advisor

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));
    }
}


Arun Patidar

Avatar

Community Advisor

@RafaelSp ,

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.