Monday, June 12, 2017

Sling Model Exporter in AEM 6.3


Hello Everyone,

Sling Model Exporter was introduced in Sling Models v1.3.0. This new feature allows new annotations to be added to Sling Models that define how the Model can be exported as JSON.

Use Case: Now the question comes why sling model exporter. So the idea is if there is a sling model and you want to fetch the same properties as a JSON response,so there is no need to create a Sling Servlet. You just need to export your sling model  using jackson exporter and that’s all. Sling Model Exporter can be used as a web service or as a rest API.

In AEM 6.3, No external dependencies required.

bundles.PNG
Fig - Required Bundle for Sling Model Exporter

The felix console already contains:

  • Apache Sling Model API (1.3.0+)
  • Apache Sling Model Implementations (1.3.0+)
  • Apache Sling Model Exporter(1.0.6)

Now create a Sling Model, But before creating the sling model you need to add some dependency for building the project


<dependency>
  <groupId>org.apache.sling</groupId>
  <artifactId>org.apache.sling.models.api</artifactId>
  <version>1.3.0</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.apache.geronimo.specs</groupId>
  <artifactId>geronimo-atinject_1.0_spec</artifactId>
  <version>1.0</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>2.8.4</version>
  <scope>provided</scope>
</dependency>

Don’t forget to make an entry of sling model package in the maven-bundle plugin.
package.PNG
Fig - Sling Model Package entry in bundle POM.xml

Now Let’s take an example of a” Hero Image” component of we-retail:
Hero-Image.PNG
Fig- Hero Component

The properties of the above component are being stored here:

properties.PNG
Fig - Dialog Values of Hero Component

Sling Model without Exporter:
To enable sling model as an exporter,the @Exporter annotation is being used.

Make a rest call with the following format:

${crx.host}:${crx.port}${path-to-resource}.${selector}.tidy.${extension}

Note:”tidy” is a default selector to show the json response in a clean format.It is not mandatory at all.

JSON Response.PNG
Fig - Hero Component Dialog value in JSON Response from Sling Model Exporter 

@Model annotation contains:

1. resourceType: This property is of String or String[] type.
The resourceType helps to know that for which resources ,the sling model needs to be exported.

@Exporter annotation contains:

1.name: Sling model provides "jackson" as exporter.
2. selector: The default value of the selector is "model".It can be override by writing this attribute.This attribute is optional.
3.extension: Sling Model needs to be exported as json.So extensions should be as “json”


Let's have a quick demo of Sling Model Exporter:
 

Jackson Exporter Options include:

Jackson Exporter Options help to manage the JSON response and control the output of the JSON

Let’s understand the Jackson Exporter Options With Example:


@ExporterOption(name = "MapperFeature.SORT_PROPERTIES_ALPHABETICALLY", value = "true")


By Default It’s value is false, then json response will be as it is.

MapperFeatureFalse.PNG


When The value is true,then it sorts the json response alphabetically based on key.

MapperFeatureTrue.PNG

Except this, MapperFeature and SerializationFeature exporter annotation has many more options.


Note: While the Apache Sling project provides the Jackson Exporter that serializes Sling Models to JSON, the Exporter framework also supports custom Exporters.


Applying Jackson Annotations:
Exporters implementations may also support annotations that can be applied inline on the Sling Model class, that can provide a finer level of control how the data is exported.

Here we go, how to use Jackson annotations with Sling Model Exporter:



To get a detailed knowledge of all the Jackson annotations, go through this link

If you have any query or suggestion then kindly comment or mail us at sgaem.blog02@gmail.com

Hope it will help you guys !!

Thanks and Happy Learning .


32 comments:

  1. Nice article. Does this support selective properties feature like query builder json servlet?

    ReplyDelete
    Replies
    1. Thanks for appreciations!

      What do you mean by selective properties feature here?

      Delete
    2. Hi Saurabh,

      In the query builder json servlet when you use selective properties feature you can tell which fields can come in the response. In the same way for instance if my resource has many properties and in the exporter response if I want to a sub set of those properties. Can it be done?

      Delete
    3. You can use Jackson Annotation @JsonIgnore for that.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. What is the advantage of this exporter when I can also retrieve the json format using localhost:4502/path-to-resource.infinity.json ?

    Please help clarify the advantages.

    ReplyDelete
    Replies
    1. Ya ashish,this is really a good question, This exporter is not only just returning the values,you can return anything from this.Let's take an example,You have taken a path in the component dialog and just want to return all the children of that path as a json.So These kind of scenario's can be handled with this.

      Delete
  4. you wrote this blog at 7:06 AM so did you sleep that night or entire night you wrote it ? Jokes apart , I appreciate your efforts in writing these blogs.

    ReplyDelete
  5. Hi Shivani,

    I have faced below interview question

    I have a normal html form there are some fields like title ,name and descrption
    name would be the page name
    description would be the page description
    title would be the page title
    when i click on submit button on that form, the page is created in my crx console
    under some node structure

    how can i do this could you please help me?

    ReplyDelete
    Replies
    1. Hi Naveen,
      While clicking on submit button,you can hit a servlet which will be using ResourceUtil API or Node API to create a page and add properties in that.

      Delete
  6. Hi Shivani,

    This is helpful article.

    But I see below compilation issue i.e. resourceTypes not found. I tried options to import resourceTypes, but have not found any. Do you know what the issue is?

    ReplyDelete
    Replies
    1. Hey Suneel, Check your Maven dependency .do you check your sling model dependency version 1.3.0?

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Hey,

    Great blog!

    I was trying to access the component using this url http://localhost:4502/content/we-retail/ca/en/experience/jcr:content/root/hero_image.model.json
    but I am getting the following error:
    org.apache.sling.models.factory.MissingElementsException: Could not inject all required fields into class com.adobe.cq.wcm.core.components.models.impl.v1.ImageImpl

    Could you please point out why this might be happening.

    Thanks & Regards,
    Prakash Iyer

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Hi Prakash,
      The issue is with already created Sling Model com.adobe.cq.wcm.core.components.models.impl.v1.ImageImpl. This situation happens when you inject a lot of field in sling model as required but the resource dont have all the values of those all injections.You can just decompile the bundle and check what this model wants.

      Delete
    3. Hello Shivani,

      Thanks for the quick reply.
      I have reinstalled the bundles for wcm components and still I am getting the same error and there are not many answers on google.
      Could you please give me some pointers as to what needs to be done.

      PS: I am a newbie and might not know all terms related to AEM

      Regards,
      Prakash Iyer

      Delete
    4. Prakash,
      Give me some time. I will look into deep and get back to you.

      Delete
    5. Hello Shivani,

      Did you get a chance to look into the issue? If so please get back as this is proving a blocker for me, I have searched a lot online but no success so far.

      Thanks in Advance

      Regards,
      Prakash Iyer

      Delete
    6. This comment has been removed by the author.

      Delete
    7. Hii Prakash,
      I checked the issue, There is a bundle in AEM 6.3 "Adobe Experience Manager Core WCM Components Core Bundle"
      In which you can see the model com.adobe.cq.wcm.core.components.models.impl.v1.ImageImpl.
      In that model, They have used SightlyWCMMode from import statement import com.adobe.cq.sightly.SightlyWCMMode;.
      I dont know why this thing is not working here. If you remove this, it will work fine. I teated it with my custom exporter with the same code.
      Looking more onto this that why wcmmode is not working.

      Delete
    8. Hey Shivani,

      I located the Adobe Experience Manager Core WCM Components Core Bundle but could not find com.adobe.cq.wcm.core.components.models.impl.v1.ImageImpl within that model. Do not know what the issue seems to be.

      Regards,
      Prakash Iyer

      Delete
    9. Can you please email me and get this resolved?

      Delete
    10. I have sent you an email, with the entire stacktrace.

      Delete
  9. HI i have a requirement like I am having an input field where i can enter text and on click of submit i have to pass the entered text to the sling models as a parameter and i have to print it returned from the slingmodels

    ReplyDelete
  10. Hi Shivangi,
    Appreciate your effort to write this nice article.

    Lets assume in a page , we have two components (A & B). Custom sling model & exporter has been implemented for both components A & B. Now can we get the exported json response for both the components via a single page request ? Looks like if we request via page level then page level entry point model is considered in rendering the json ignoring the component models. Is the understanding correct ?

    ReplyDelete
  11. HI Shivani,

    Thanks for this article.

    I have created exporter component and component added to the page.
    I am able to get the json response from below
    http://localhost:4502/content/home-buying/find-an-agent/jcr:content/content/iframe.model.json

    Can we get the same response using page URL like
    http://localhost:4502/content/home-buying/find-an-agent/iframe.model.json

    Here my page is find-an-agent and exporter component is iframe

    Thanks , Ramesh

    ReplyDelete
  12. HI Shivani,
    I follwed the same step to create sling exporter but getting below error.
    Note :- "test1" is my selector
    Invalid recursion selector value 'test1'

    Cannot serve request to /content/aem63arch12/en/testexporter/jcr:content/root/responsivegrid/slingexporter.test1.json in org.apache.sling.servlets.get.DefaultGetServlet

    Do you have any idea why i am getting this error?

    ReplyDelete
  13. I have a scenario where i have created a custom sling exporter with some defined fields in JSON format. Is there a way we can Inject additional fields without doing code change as there may be need to add some fields later

    ReplyDelete