Issue in Sling Model instantiating from Sightly | Community
Skip to main content
Level 2
September 17, 2025
Solved

Issue in Sling Model instantiating from Sightly

  • September 17, 2025
  • 2 replies
  • 1069 views

Hi 

I’m trying to use a simple Sling Model from HTL, but the model never instantiates (null bindings). I suspect I’m missing something obvious with the adaptable.

Sling Model

package com.acme.core.models;

import javax.inject.Inject;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;

@Model(
adaptables = Resource.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class TeaserModel {

@586265
private String title;

public String getTitle() {
return title;
}
}

 

Sightly

<div data-sly-use.m="com.acme.core.models.TeaserModel">
<h2>${m.title}</h2>
</div>

 

When I check the logs here is what I get, what wrong here?

org.apache.sling.models.impl.ModelAdapterFactory Could not adapt
org.apache.sling.api.SlingHttpServletRequest to com.acme.core.models.TeaserModel

Best answer by SantoshSai

Hi @anujara,

I think, HTL tries to adapt from the request by default, but your model is Resource-adaptable.

You have 2 options:

1. Make the model request-adaptable (HTL unchanged):

@Model(
  adaptables = org.apache.sling.api.SlingHttpServletRequest.class,
  defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class TeaserModel {
  @org.apache.sling.models.annotations.injectorspecific.ValueMapValue(
    name = org.apache.jackrabbit.JcrConstants.JCR_TITLE
  )
  private String title;
  public String getTitle() { return title; }
}

2. Keep Resource-adaptable and force resource adaptation in HTL:

<div data-sly-use.m="${'com.acme.core.models.TeaserModel' @ resource=resource}">
  <h2>${m.title}</h2>
</div>

Also, I see property name mismatch in your code: Field is title, but the JCR property is jcr:title. With plain @Inject it won’t map.
Try to use @ValueMapValue(name = "jcr:title") (shown above) or rename the field to jcr:title (not recommended).

2 replies

giuseppebaglio
Level 10
September 17, 2025

Your model says it adapts from Resource.class, but HTL uses the SlingHttpServletRequest as the adaptable by default when using data-sly-use. Because the model isn’t configured to adapt from request, adaptation fails and returns null. 

Change your model to adapt from SlingHttpServletRequest.class

@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class TeaserModel { @586265 private String title; public String getTitle() { return title; } }

This way, when HTL runs data-sly-use, it adapts the current request to your model, which matches the adaptable.

 
 
SantoshSai
Community Advisor
SantoshSaiCommunity AdvisorAccepted solution
Community Advisor
September 17, 2025

Hi @anujara,

I think, HTL tries to adapt from the request by default, but your model is Resource-adaptable.

You have 2 options:

1. Make the model request-adaptable (HTL unchanged):

@Model(
  adaptables = org.apache.sling.api.SlingHttpServletRequest.class,
  defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class TeaserModel {
  @org.apache.sling.models.annotations.injectorspecific.ValueMapValue(
    name = org.apache.jackrabbit.JcrConstants.JCR_TITLE
  )
  private String title;
  public String getTitle() { return title; }
}

2. Keep Resource-adaptable and force resource adaptation in HTL:

<div data-sly-use.m="${'com.acme.core.models.TeaserModel' @ resource=resource}">
  <h2>${m.title}</h2>
</div>

Also, I see property name mismatch in your code: Field is title, but the JCR property is jcr:title. With plain @Inject it won’t map.
Try to use @ValueMapValue(name = "jcr:title") (shown above) or rename the field to jcr:title (not recommended).

Santosh Sai
AnujaRaAuthor
Level 2
September 17, 2025

@santoshsai Thanks for the last point you mentioned about mapping title field, inititally I tried SlingHttpServletRequest but may be because of field mismatch it didn't worked but now it worked!