AEM SPA | URL Shortening | Community
Skip to main content
iamnjain
Community Advisor
Community Advisor
November 17, 2023
Solved

AEM SPA | URL Shortening

  • November 17, 2023
  • 4 replies
  • 5267 views

Hello,

 

I am facing issue in AEM SPA shorten url page ui rendering.

So, my setup is as below,

 

1. I have template structure depth set to 0 which will trigger a network call to root json i.e. en.model.json and then respective page.model.json

2. I added sling mapping under /etc/map which seems to be working fine. My sling mapping properties are

sling:match = localhost.4503/us

sling:internalRedirect = /content/site-name/us

 

Now, page.html call and other model.json call is success if I hit the url "http://localhost:4503/us/test.html" and all react clientlibs loads as well in network tab.

 

Can you please help what am I doing wrong here and what can be done to work this?

 

Thanks.

 

@kautuk_sahniif you help tag AEM SPA experts here. It will help.

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by iamnjain

Hi @kautuk_sahni 

No, issue is not fixed yet.

 

I am unable to find getRootUrl() method to override in com.adobe.aem.spa.project.core.models.Page


This issue fixed with one change.

On spa root template page policy, we need to uncheck isRoot checkbox under Hierarchical Structure. Then, it will not send a extra rootpage.model.json call to AEM and only a single call requestedpage.model.json to render page content and page will load.

4 replies

partyush
Community Advisor
Community Advisor
November 17, 2023

@iamnjain 

 

It appears that your setup is generally correct, but let's check a few things:

  1. Ensure Sling Mappings are Active:

    • Confirm that your Sling mappings are active by checking the Apache Sling Mappings console (/system/console/jcrresolver) to see if your mappings are listed and have the correct configurations.
  2. Check Content Structure:

    • Validate that the content structure under "/content/site-name/us" matches the expected structure for your SPA. Ensure that pages, components, and templates are organized correctly.
  3. Dispatcher Configuration:

    • If you are using the AEM Dispatcher, verify the dispatcher configuration to ensure that it allows requests to your SPA pages. Check the dispatcher logs for any potential issues.
  4. JSON Responses:

    • Manually access "http://localhost:4503/us/test.html" and check the JSON responses (en.model.json and page.model.json). Ensure they are being generated correctly and do not contain errors.
  5. Network Calls:

    • Use browser developer tools to monitor network calls. Check if the requests to en.model.json and page.model.json return the expected data without errors.
iamnjain
Community Advisor
iamnjainCommunity AdvisorAuthor
Community Advisor
November 17, 2023

yes @partyush 

 

All things which you mentioned is in place.
I am not using dispatcher, so testing directly on local publish instance.

 

One thing to notice here is,

1. I have template structure depth set to 0 which will trigger a network call to root json i.e. en.model.json and then respective page.model.json

 

Will this cause any issue in rendering UI for SPA?

partyush
Community Advisor
Community Advisor
November 17, 2023

Hi @iamnjain 

 

Verify that the generated JSON structure aligns with the expectations of your SPA. Confirm that it includes the necessary data for rendering your SPA components.

 

And also 

 

Ensure that your SPA components are coded to handle the asynchronous loading of data from both the root JSON and subsequent page JSONs. Make certain that your JavaScript logic waits for the required data before attempting to render UI components.

lukasz-m
Community Advisor
Community Advisor
November 17, 2023

Hi @iamnjain,

If I good understand you are trying to short urls in SPA in the same way you would do that using HTL, right?

If so, then this will not work, this is one of the limitations of SPA, you can find all the limitations under https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/implementing/developing/hybrid/editor-overview.html?lang=en#limitations

Nevertheless, that does not mean you can't have short links, but in that case you will have to use resourceResolver.map method explicitly, on each property in your sling model that contains url you would like to be short. It will then be exported in short form in your model.json

iamnjain
Community Advisor
iamnjainCommunity AdvisorAuthor
Community Advisor
November 17, 2023

Hi @lukasz-m 

 

Thanks for your response.

So I understand the limitations.

 

The page I am testing doesn't have any Links, only a text component which is not rendering with shorten URL and render fine with long URL.

How it will work, if you can help. I explained the scenario above.

lukasz-m
Community Advisor
Community Advisor
November 17, 2023

If you have link inside text component this will be a bit more difficult, you will have to:

  1. Extract urls from text, e.g. base on a fact urls are inside href attribute of anchor html element.
  2. Create short url using resourceResolver.map method.
  3. Put back short url into your text.

Of course you will still need a sling mapping, because it will be used by map method from resourceResolver to create short url.

Here is a sample code of Sling model that extends Text core component to create short url inside text:

import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.models.annotations.DefaultInjectionStrategy; import org.apache.sling.models.annotations.Exporter; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Via; import org.apache.sling.models.annotations.injectorspecific.Self; import org.apache.sling.models.annotations.via.ResourceSuperType; import com.adobe.cq.wcm.core.components.models.Text; import java.util.Optional; import java.util.regex.Pattern; @Model( adaptables = SlingHttpServletRequest.class, adapters = { TextModel.class, ComponentExporter.class }, resourceType = TextModel.RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL ) @Exporter( name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION ) public class TextModel implements Text { private static final Pattern HREF_PATTERN = Pattern.compile("(?i)\\bhref\\s*=\\s*[\"'](\\S+)[\"']"); static final String RESOURCE_TYPE = "smaple/components/text"; @Self private SlingHttpServletRequest request; @Self @2434638(type = ResourceSuperType.class) protected Text delegate; @9944223 public String getText() { return Optional.ofNullable(delegate.getText()) .map(this::mapLinks) .orElse(null); } @9944223 public String getExportedType() { return RESOURCE_TYPE; } private String mapLinks(String text) { var matcher = HREF_PATTERN.matcher(text); var output = new StringBuilder(); while (matcher.find()) { var hrefValue = matcher.group(1); var mappedHrefValue = map(request, hrefValue); matcher.appendReplacement(output, "href=\"" + mappedHrefValue + "\""); } matcher.appendTail(output); return output.toString(); } private String map(SlingHttpServletRequest request, String path) { ResourceResolver resourceResolver = request.getResourceResolver(); return (request != null) ? resourceResolver.map(request, path) : resourceResolver.map(path); } }
Level 3
November 18, 2023

@iamnjain We did resolve urls shortening long back on the react-spa with custom changes. If may I remember correctly you have url short all the :path params in the model.json. So Adobe spa module checks if the url of page in browser(request uri) matches the :path in the model.json then there will be rendering of page with all the details. If it is not, spa page will have no content.

 

Reference issues: 

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/aem-spa-react-dispatcher-setup/m-p/396676#M12670

iamnjain
Community Advisor
iamnjainCommunity AdvisorAuthor
Community Advisor
November 20, 2023

Hi @bipinch1 

 

Can you please add code snapshot for the same which you modified?

 

Did you extended any OOTB Sling models for this?
This will help me. Thanks.

Level 3
November 20, 2023

Sorry, as I do not have access to the code now will not be able to provide the code snippet. If I remember it correctly, I created a spa project out of We-Retail Journal project: https://github.com/adobe/aem-sample-we-retail-journal and have to short url at these methods getExportedPath(), getModelUrl() and getChildPageModels() in hierarchy page model classes. Remember to have :path should match the request url to render anything on spa.

kautuk_sahni
Community Manager
Community Manager
November 23, 2023

@iamnjain Did you find the suggestions from users helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.

Kautuk Sahni
iamnjain
Community Advisor
iamnjainCommunity AdvisorAuthor
Community Advisor
November 23, 2023

No @kautuk_sahni 

I am still not clear what and where to make the changes to get it working.

kautuk_sahni
Community Manager
Community Manager
November 23, 2023

The original problem is that the AEM SPA is triggering unnecessary network calls to the root JSON (en.model.json) and the respective page.model.json for every component rendering. This is because the template structure depth is set to 0, which tells the AEM SPA to load all of the child components of a page in one go. This is causing performance issues and preventing the content from rendering correctly.

To solve this problem, you need to extend the core Page model to tweak the logic of URL shortening. This will allow you to control how the URLs are generated and avoid unnecessary network calls.

Here's how to extend the core Page model to solve the problem:

  1. Create a custom Page model class. This class should extend the com.adobe.aem.spa.project.core.models.Page class.

  2. Override the getRootUrl method in your custom Page model class. This method is responsible for generating the root URL for the page. In your override, you should check if the template structure depth is 0. If it is, you should return the full URL of the page. Otherwise, you should return the root URL as generated by the default getRootUrl method.

  3. Inject your custom Page model class into the AEM SPA. This can be done by adding a Sling resource provider for your custom Page model class.

Once you have completed these steps, the AEM SPA will use your custom Page model class to generate the root URLs for pages. This will prevent unnecessary network calls and allow the content to render correctly.

@9944223

public String getRootUrl() {

if (getTemplateStructureDepth() == 0) {

return getPageModel().getFullUrl();

} else {

return super.getRootUrl();

}

}

OR 

 

Have tried the option of "Exclude Root Levels"?

Kautuk Sahni