6
votes

The Adobe AEM software provides several classes which can take an apache Sling Resource and adapt it to another class like so:

Page page = resource.adaptTo(Page.class);

To use this syntax with classes that you author and control this boils down to simply implementing the Adaptable interface.

However, if you want to enable a Resource to adaptTo your new custom class, is seems that you have to implement the AdapterFactory interface and register it in OSGI.

This is how the Adobe website describes it:

By an AdapterFactory, which can map arbitrary objects. The objects must still implement the Adaptable interface and must extend SlingAdaptable (which passes the adaptTo call to a central adapter manager). This allows hooks into the adaptTo mechanism for existing classes, such as Resource.

I have walked through the SlingScriptAdapterFactory code, but ultimately I am not connecting the dots here. Basically I want to do this:

MyClass myClass = Resource.adaptTo(MyClass.class);

Do I create a class that implements AdapterFactory and simply deploy it with the package expecting that Sling will just find it by type or is there more to it?

2

2 Answers

5
votes

Here is a little bit better documentation https://sling.apache.org/documentation/the-sling-engine/adapters.html

So you should implement the Adaptable interface, as you already described. Then create a properly annotated AdapterFactory:

@Component
@Service(value=org.apache.sling.api.adapter.AdapterFactory.class)
@Properties({
   @Property(name = "adaptables", value = { "org.apache.sling.api.resource.Resource" }),
   @Property(name = "adapters", value = { "org.sling.MyClass" })
})
public class MyAdapterFactory implements AdapterFactory{
    public  <AdapterType> AdapterType getAdapter(final Object adaptable, Class<AdapterType> type){
          return new MyClassAdapter(adaptable);   
    }     
}
3
votes

Note that I've been working on a simpler way to create Sling adapters, by annotating methods with a new @Adapter annotation, as in

  @Component
  @Service
  public class C implements AdapterMethodsProvider {
    @Adapter
    public CustomerRecord convert(Resource r) { ... }

    @Adapter
    public Person adaptToPerson(Resource r) { ... }
  }

See https://issues.apache.org/jira/browse/SLING-2938 for details, but note that this is not even in the Sling trunk yet, so it will take some time before it's released and available in AEM/CQ.