Expand my Community achievements bar.

SOLVED

Sling model exporter

Avatar

Level 6

Hi All,

 

Hope you all are fine.

 

Although, I don’t have any specific problem related to exporter but would like to understand best approach while serving content from AEM to some react component.

 

For example:

 

We have a ABC component in which all labels should be served from AEM and all dynamic logic should be written in react component. We have multiple similar components to implement.

It is not a SPA application.

so, in our AEM component HTL, we simply write a container div with some data attribute

 

 <div data-component="ABC"></div>.

 

Now, How AEM should provide all dialog labels to REACT.

 

  1.  Through Sling model exporter 
  2.  Any other way (would like to learn from experts here).

 

SLING MODEL:

 

 

@Model(adaptables = SlingHttpServletRequest.class, resourceType = ABC.RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
@exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class ABC {
protected static final String RESOURCE_TYPE = "mysite/components/abc";
@ValueMapValue(name = "title")
private String title;
@ValueMapValue(name = "subtitle")
private String subtitle;

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getSubtitle() {
return subtitle;
}

public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
}
}

 

Using, approach 1,  

 

1) Should we create one sling model exporter for each component?

2)

example URL for ABC component:

/content/experience-fragments/mysite/us/en/test/master/jcr:content/root/abc.model.json

 

If we provide this URL to react (ui.frontend), can it be accessed from REACT without any further configurations needed like allowing "model" selector in config manager or at dispatcher level?

 

3) Is it necessary to create single exporter for each component or we can create a centralized exporter that can be used for all similar components.

 

4) Any better and optimized way to manage such scenarios?

 

Thank you in advance.

 

Regards,

AP

 

 

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @arvind ,

 

We have implemented the same scenario by using Content APIs instead of using AEM components.

 

PROS:

  • Very easy to create content fragment model
  • Content authors can easily create content-fragments, based on the requirement
  • Can be exposed as an API
  • Can be used by both desktop and apps

You can follow below steps to create Content APIS, which could be consumed by React app or any other app for that matter, as an API.

 

Step 1: Create the Content Fragment Model

https://localhost:4502/libs/dam/cfm/models/console/content/models.html/conf/{project folder}

Drag Drop the fields that you need and also you can define whether those are optional or mandatory and their maxlength

 

Step 2: Create Content Fragments

Based on the above created Content Fragment Model, you can create different content fragments as assets in /content/dam

 

Step 3: Consuming Content Fragments

You can create pages in AEM  and using Content Fragment core component, you can select different content fragments on the page form the paths created in Step 2.

 

Step 4: Exposing Content Fragments

So in AEM, the content from the content fragments can be exposed out of the box using model.json via a page, like below

. https://www.domain.com/en/content-service/samplepage.model.json

This will be the page, you will create in Step 3

 

Now this json exposes the content, which is not much readable and will be tougher for FE to consume

So, you can build a wrapper over it, to consume this URL and expose a nice formatted json.

In our case we are calling the above URL from a Spring Boot Application, formatting the json and exposing it as an API, say https://api.domain/content-service/whatever

Let me know if you need any support in implementing this.

 

Thanks,

Chitra

View solution in original post

10 Replies

Avatar

Correct answer by
Community Advisor

Hi @arvind ,

 

We have implemented the same scenario by using Content APIs instead of using AEM components.

 

PROS:

  • Very easy to create content fragment model
  • Content authors can easily create content-fragments, based on the requirement
  • Can be exposed as an API
  • Can be used by both desktop and apps

You can follow below steps to create Content APIS, which could be consumed by React app or any other app for that matter, as an API.

 

Step 1: Create the Content Fragment Model

https://localhost:4502/libs/dam/cfm/models/console/content/models.html/conf/{project folder}

Drag Drop the fields that you need and also you can define whether those are optional or mandatory and their maxlength

 

Step 2: Create Content Fragments

Based on the above created Content Fragment Model, you can create different content fragments as assets in /content/dam

 

Step 3: Consuming Content Fragments

You can create pages in AEM  and using Content Fragment core component, you can select different content fragments on the page form the paths created in Step 2.

 

Step 4: Exposing Content Fragments

So in AEM, the content from the content fragments can be exposed out of the box using model.json via a page, like below

. https://www.domain.com/en/content-service/samplepage.model.json

This will be the page, you will create in Step 3

 

Now this json exposes the content, which is not much readable and will be tougher for FE to consume

So, you can build a wrapper over it, to consume this URL and expose a nice formatted json.

In our case we are calling the above URL from a Spring Boot Application, formatting the json and exposing it as an API, say https://api.domain/content-service/whatever

Let me know if you need any support in implementing this.

 

Thanks,

Chitra

Avatar

Level 2

Hi @ChitraMadan,

   The above information was very useful & interesting as well. If possible, please write a article on medium platform, it will be a great read.

Thanks.

Avatar

Community Advisor
Appreciate the feedback @GnanendraPonnala. Sure, will write a blog about it. Thanks

Avatar

Level 2

HI Chitra,

 

  Can you please help me on this as we are using the json only to out put the lables defined in the aem componnets which will be usedd by vue front end module.

 

Avatar

Community Advisor

Hi @arvind ,

 

You can refer below video to undertstand the concept-

https://www.youtube.com/watch?v=IETEWVK5vl8

 

You need to create a sling model for each component. Also, if your requirement is to captures Asset meta-data/Content fragment then there are APIs available which you can directly use from React component (usually GET calls)

 

CF HTTP API and Server side API-

https://www.youtube.com/watch?v=wtO_GwZggig

 

Asset API-

https://www.youtube.com/watch?v=Yn7ybOwfIYY

 

Also, check this old thread-

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/invalid-recursion-selector...

Avatar

Level 6

@Ritesh_Mittal  Thank you for your reply.

 

But As I written earlier, our project is not AEM SPA Based archetype.

 

Ours is simple AEM plus react project so ui.frontend module is not same as mentioned in many articles or even in your good video.

 

This is the main issue.

 

Do you have any similar approach for AEM REACT  project but not with SPA one.

 

Regards,

AP

Avatar

Level 6

@ChitraMadan 

 

Thank you for your reply.

 

Yeah we understand Content fragment approach but unfortunately, We dont want to create a new  Content fragment for a component which is already present and author can give all properties values in same components only. e.g CART.  

 

Using this CF approach, we need to do two things:

 

  1. Create Cart component in AEM in which we provide only container for React components.
  2. Create EF which takes care of all properties that is needed for Cart components and then expose it to REACT by some means.

 

Can we directly send properties from Cart components only to REACT but again It is not AEM SPA editor one so I dont think one to one AEM React component mapping is possible

 

Thank you in advance.

 

 

 

 

 

 

Avatar

Community Advisor

Hi @arvind 

 We had similar requirement but in our case we had very few authorable components for that we used sling model exporter and for labels and configurations which needed for site e.g googlemap key, languages available .captcha key etc we created separate API and exposed that to react component.

 

Thanks

Dipti Chauhan 

Avatar

Employee Advisor

@arvind  Instead of using Sling Model Exporter, you can have simple sling model and have a common method in it to create a json object using all the fields in the component, serialize using gson. You can pass this serialized json into the data- attribute in the component's HTL which can be read by the react component

Avatar

Community Advisor

Hi @arvind,

You can make use of the Sling Model Exporter approach. Few comments inline in green to the pointers you have mentioned 

 

1) Should we create one sling model exporter for each component? Yes. This is because we tie the ExportedType method of ComponentExporter interface to the component Resource type and also Sling Model adaptables - We use a specific request/resource path such that it adapts to a respective Model. We cannot generalize a Model to handle/inject all properties

2)

example URL for ABC component:

/content/experience-fragments/mysite/us/en/test/master/jcr:content/root/abc.model.json

 

If we provide this URL to react (ui.frontend), can it be accessed from REACT without any further configurations needed like allowing "model" selector in config manager or at dispatcher level? You can access from React app using fetch or axios(NPM module) GET request provided origin(in this case, React App) is allowed/whitelisted in OSGi configs - Apache Sling Referer Filter Config and Adobe Granite Cross Origin Resource Sharing Policy in AEM publish instance from which you are accessing the content. From Dispatcher standpoint, allow the URL in /filter (generalize using regex based on the content path)

 

3) Is it necessary to create single exporter for each component or we can create a centralized exporter that can be used for all similar components. This query looks similar to pointer #1. If not, please elaborate.

 

4) Any better and optimized way to manage such scenarios? Other options for exposing content in this context -

  • Content Fragments (which you don't want to create one)
  • Using Sling Servlets registered with desired selector and extension (Old way, Before AEM content services)

In brief,

  • For AEM SPA project, content exposed by Sling Model exporter is accessible as "props" in React terms due to Component Mapping part of AEM SPA React SDK
  • In Non SPA React project, accessing content from AEM is like making a REST API call from React app provided AEM allows the respective origin to access.