HomeBackend Development › Sling Models deep dive

Sling Models deep dive

Purpose: Reference for injection, adaptables, exporters, delegation and model pitfalls beyond the Session 5 basics.

Who this page is for

AudienceWhy it matters to you
Backend engineersDaily reference
Frontend engineersRead-fluency

Adaptable choice

AdaptableUse whenTrade-off
ResourcePure content adaptationSimplest, most testable, cacheable
SlingHttpServletRequestYou need selectors, params, WCM contextHeavier; don't cache derived state across requests

If a model only reads content, adapt from Resource. Add @Via and @Self composition before reaching for request adaptation.

Injectors reference

AnnotationSourceNotes
@ValueMapValueProperty of current resource@Named for property name ≠ field name
@ChildResourceChild node(s)Inject as Resource, model class, or List thereof
@SelfThe adaptableAlso: adapt the adaptable to another model
@OSGiServiceService registryOptional=true for soft deps
@ScriptVariablecurrentPage, pageManager, wcmmode…Request-adaptable only
@RequestAttributeRequest attributeFor values passed via data-sly-resource requestAttributes
@SlingObjectresolver, response, etc.Utility injection

Patterns

Delegation (extending Core Components)

Wrap the product model rather than re-implementing it:

@Model(adaptables = SlingHttpServletRequest.class, adapters = Title.class,
       resourceType = "phi-academy/components/title")
public class PhiTitleModel implements Title {
    @Self @Via(type = ResourceSuperType.class)
    private Title delegate;                       // product implementation

    @Override public String getText() {           // decorate one method
        return "PHI | " + delegate.getText();
    }
    // …delegate everything else
}

Exporter

@Exporter(name="jackson", extensions="json") + resourceType binding → .model.json output. Control the shape with Jackson annotations; never expose repository internals (paths, node names) you don't want to commit to as API.

Pitfalls

PitfallConsequenceFix
REQUIRED injection defaultModel is null in HTL when any field missingOPTIONAL strategy + @Default
Logic in constructorsRuns before injection — NPEsUse @PostConstruct
Stateful/mutable modelsModels are per-request; sharing state breaksKeep them read-only adapters
Heavy work in gettersRepeated per HTL accessCompute once in @PostConstruct
Adapting via resolver.adaptTo in loopsPerformanceBatch/query smarter, adapt once

Quick navigation