Expand my Community achievements bar.

Applications for the 2024-2025 Adobe Experience Manager Champion Program are open!
SOLVED

Unable to call sling model class from servlet

Avatar

Level 9

 I am trying to call one of the sling model methods from servlet but I could not adapt the resource object to the sling model. 

 

Here is my sling model.

 

 

@Model(
        adaptables = { SlingHttpServletRequest.class, Resource.class },
        adapters = ProductDetail.class,
        resourceType = ProductDetailImpl.RESOURCE_TYPE)
@Exporter(
        name = CommonConstants.JACKSON,
        extensions = CommonConstants.JSON,
        options = { @ExporterOption(
                name = CommonConstants.SERIALIZATION_FEATURE + "." + CommonConstants.WRAP_ROOT_VALUE,
                value = CommonConstants.TRUE) })


public class ProductDetailImpl implements ProductDetail
{
        @JsonProperty("productDetail")
	@Override
	public String getProductDetail() {
		return productDetail;
	}
}

 

 

I am trying to call the getEventBeanList method in my below servlet, I can see the valid Resource object and when I try to adaptTo this resource to sling model class I get a null pointer exception. Any ideas why I am getting NPE?

 

[UPDATE]

I tried to check the status using http://localhost:4502/system/console/adapters. Interestingly my sling model class is marked as red but there is no reason given. In fact the sling model works as expected individually but I am not sure why this is marked in red color. Moreover all working sling models are marked as red but it is working as expected.

 

Mario248_0-1704905902806.png

 

 

 

 

protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
throws ServletException, IOException {
Resource resource = request.getResourceResolver().getResource("/content/actualcontent");
LOGGER.info("test 1--- "+resource.getResourceType());  //platform/component/content/produtdetail
boolean isValidResource = resource.isResourceType("platform/component/content/produtdetail");
LOGGER.info("test 2-- "+ isValidResource);
if(isValidResource && "platform/component/content/produtdetail".equalsIgnoreCase(resource.getResourceType())) {
        ProductDetailImpl product = resource.adaptTo(ProductDetailImpl.class);
        String  productDetail = product.getProductDetail();
        LOGGER.info("productDetail: " +productDetail);
}

}

 

 

 

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Do you see any errors in your bundle, if you click on the adapter highlighted in red, do you see extra info?

I tried to reproduce what you are doing but everything is working fine for me. What comes to my mind is that perhaps you have a required field that is not available in the resource that you are trying to adapt from, did you try to add "defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL" in your model signature?

 

This is what I did and works fine:

@Model(
        adaptables = { SlingHttpServletRequest.class, Resource.class },
        adapters = ProductDetailModel.class,
        resourceType = ProductDetailModelImpl.RESOURCE_TYPE)
@Exporter(
        name = "jackson",
        extensions = "json"
       )
public class ProductDetailModelImpl implements ProductDetailModel {

    public static final String RESOURCE_TYPE = "oshynDemo/components/helloworld";

    @Override
    public String getProductDetail() {
        return "works";
    }
    
}

Servlet:

...//Servlet signature missing
public class EstebanServlet extends SlingSafeMethodsServlet {

    
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(final SlingHttpServletRequest req,
            final SlingHttpServletResponse resp) throws ServletException, IOException {
        final Resource resource = req.getResourceResolver().getResource("/content/oshynDemo/us/en/blog/jcr:content/root/container/container/helloworld");
        resp.setContentType("text/plain");
        ProductDetailModel model = resource.adaptTo(ProductDetailModel.class);
        resp.getWriter().write("Title = " + model.getProductDetail() );
    }

 The resource I am trying to adapt from: "/content/oshynDemo/us/en/blog/jcr:content/root/container/container/helloworld"

Looks like this:

EstebanBustamante_0-1704908154877.png

Hope this helps

 



Esteban Bustamante

View solution in original post

9 Replies

Avatar

Community Advisor

You need to make sure the Resource from "/content/actualcontent" has the resourceType equal to 

ProductDetailImpl.RESOURCE_TYPE.

 

Otherwise, You could try to use "modelFactory" https://www.javadoc.io/doc/org.apache.sling/org.apache.sling.models.api/1.3.6/org/apache/sling/model...  to get more details about the error.

 

Hope this helps

 



Esteban Bustamante

Avatar

Level 9

thanks for your response. I can not access "RESOURCE_TYPE" on resource object. Could you please provide me more info and maybe code snippet?

Avatar

Community Advisor

Are you saying you cannot check the properties from this node "/content/actualcontent"? One of the properties is "resourceType" which is the value you need to validate.

You should be able to validate this via crx/de (if have you have access) or via the Repository Browser https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/implementing/develo... which is available in the developer console.

 

 

 



Esteban Bustamante

Avatar

Level 9

sorry, I got you now. yeah I checked the resource type using resource.getResourceType() and cross checked the same on crxde and sling model on @Model annotation class. All the have the same value which is "platform/component/content/produtdetail". the below IF condition is getting passed but getting NPE while adapting resource with sling model class.

 

 

Resource resource = request.getResourceResolver().getResource("/content/actualcontent");
LOGGER.info("test 1--- "+resource.getResourceType());  //platform/component/content/produtdetail
boolean isValidResource = resource.isResourceType("platform/component/content/produtdetail");
LOGGER.info("test 2-- "+ isValidResource);
if(isValidResource && "platform/component/content/produtdetail".equalsIgnoreCase(resource.getResourceType())) {
        ProductDetailImpl product = resource.adaptTo(ProductDetailImpl.class);
        String  productDetail = product.getProductDetail();
        LOGGER.info("productDetail: " +productDetail);
}

 

 

I tried to check the status using http://localhost:4502/system/console/adapters. Interestingly my sling model class is marked as red but there is no reason given. In fact the sling model works as expected individually but I am not sure why this is marked in red color. Moreover all working sling models are marked as red but it is working as expected.

 

Mario248_0-1704905902806.png

 

Avatar

Correct answer by
Community Advisor

Do you see any errors in your bundle, if you click on the adapter highlighted in red, do you see extra info?

I tried to reproduce what you are doing but everything is working fine for me. What comes to my mind is that perhaps you have a required field that is not available in the resource that you are trying to adapt from, did you try to add "defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL" in your model signature?

 

This is what I did and works fine:

@Model(
        adaptables = { SlingHttpServletRequest.class, Resource.class },
        adapters = ProductDetailModel.class,
        resourceType = ProductDetailModelImpl.RESOURCE_TYPE)
@Exporter(
        name = "jackson",
        extensions = "json"
       )
public class ProductDetailModelImpl implements ProductDetailModel {

    public static final String RESOURCE_TYPE = "oshynDemo/components/helloworld";

    @Override
    public String getProductDetail() {
        return "works";
    }
    
}

Servlet:

...//Servlet signature missing
public class EstebanServlet extends SlingSafeMethodsServlet {

    
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(final SlingHttpServletRequest req,
            final SlingHttpServletResponse resp) throws ServletException, IOException {
        final Resource resource = req.getResourceResolver().getResource("/content/oshynDemo/us/en/blog/jcr:content/root/container/container/helloworld");
        resp.setContentType("text/plain");
        ProductDetailModel model = resource.adaptTo(ProductDetailModel.class);
        resp.getWriter().write("Title = " + model.getProductDetail() );
    }

 The resource I am trying to adapt from: "/content/oshynDemo/us/en/blog/jcr:content/root/container/container/helloworld"

Looks like this:

EstebanBustamante_0-1704908154877.png

Hope this helps

 



Esteban Bustamante

Avatar

Level 6

@Mario248 
Please confirm that with above implementation deployed on your instance, is your bundle is in active state or not?
Getting NPE on adaptTo with correct resource Type can be because the bundle is not active.

ALSO:
Please add this property in @Model annotation in your sling model

defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
And then build your code and try if it works.

Avatar

Level 9

Thank you Arun. I am pretty much trying the same approach.

Avatar

Administrator

@Mario248 Did you find the suggestions from users helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.



Kautuk Sahni