Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

How to create URLS to read information from a content fragment?

Avatar

Level 5

Hello, currently I have a servlet that sends to call an api that brings a JSON, this JSON are products and can be X amount, in order once called these products I save them in content fragments.

 

And the next part is that I have a dynamic component, the component doesn't show information until by means of the url you indicate him that product you want to visualize to achieve this you have the following link

 

domain.com/products

 

you will have to indicate in the url that product you want to visualize with a selector of the following way:

 

domain.com/products.product1

 

the variable product1 is a variable named product_title and is the content fragment product id, and this way the component will go to look for in the content fragment of the jcr that product and will show the information. It works everything and perfect, but now what I want to do is that instead of using

 

domain.com/products.product1

 

use now

 

domain.com/products/product1

 

That is to say to use a / instead of .

 

The problem is that if I use a / AEM detects me as if looking for a page created and existing in the path after products, which is not so, what can I do to add that rule or modification?

This is my component model code:

@Model(adaptables = {Resource.class, SlingHttpServletRequest.class})
public class ProductModel {

    private static final Logger log = LoggerFactory.getLogger(ProductModel.class);

    @Self
    private SlingHttpServletRequest request;

    @SlingObject
    private ResourceResolver resourceResolver;

    @Optional
    private String productTitle;

    // Declaration of the rest of the values

    @PostConstruct
    protected void init() {
        String[] selectors = request.getRequestPathInfo().getSelectors();
        String cfProductName = selectors[0];

        Resource productResource = resourceResolver.getResource("/content/dam/tfs/us/en/test-folder/products/" + cfProductName);
        if (productResource != null) {
            ContentFragment contentFragment = productResource.adaptTo(ContentFragment.class);
            if (contentFragment != null) {
                Iterator<ContentElement> elements = contentFragment.getElements();
                while (elements.hasNext()) {
                    ContentElement element = elements.next();
                    switch (element.getName()) {
                        case "product_title":
                            productTitle = getValueOrDefault(element);
                            break;
                        case "brand_name":
                            brandName = getValueOrDefault(element);
                            break;
                         // Rest of the cases of the values
                    }
                }
            } else {
                log.warn("Resource is not a Content Fragment: {}", productResource.getPath());
            }
        } else {
            log.warn("No product found for productTitle: {}", cfProductName);
        }
    }

    private String getValueOrDefault(ContentElement element) {
        return element != null && element.getContent() != null ? element.getContent() : "";
    }

    private String[] getArrayOrDefault(ContentElement element) {
        return element != null && element.getContent() != null ? element.getContent().split(",") : new String[]{};
    }

    public String getProductTitle() {
        return productTitle;
    }
   // Rest of the getters methods
}
Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @Aaron_Dempwolff 
The rewrite rule shared as sample. you need to write your own based on content taxonomy.

For example if Product path are at 

/content/tfs/us/en/test-folder/products/T.html

then 

#Example product redirect
^/content/tfs/([a-zA-Z]{2})/([a-zA-Z]{2})/test-folder/products/(.*) /content/tfs/$1/$2/test-folder/products.$3 [PT,L]

 



Arun Patidar

View solution in original post

7 Replies

Avatar

Community Advisor

@Aaron_Dempwolff 

One approach would be that you can try using dispatcher rule to rewrite the URL's

as example.com/abc/xyz.html to example.com/abc.xyz.html

RewriteRule ^([^/]+)/([^/]+)\.html$ /$1.$2.html [L]

(Add the appropriate rewrite condition for this rule)

 

 

Avatar

Community Advisor

Yes, Use rewrite rule. No need to change any backend logic

 

#product redirect
RewriteRule ^/products/(.*) /product.$1 [PT,L]

 



Arun Patidar

Avatar

Level 5

From what I understand, modifying the rewrite.rules or dispatcher will only redirect the page so that if the user types

domain/products/product1

the url will be redirected or disguised.

domain/products.product1

but that does'nt make the model work, since it is designed to use a selector (.)

I have tried with the rule that you told me and I get the same error, it tries to access a page that already exists or is in AEM, which is not the case.

If I use the selector (.) it works

Aaron_Dempwolff_1-1725893904456.png


But If I use the slash (/) even with the rewrite rule it still doesn't work

Aaron_Dempwolff_2-1725893962736.png



I got the next error:

Resource at '/content/tfs/us/en/test-folder/products/T.html' not found: No resource found

Cannot serve request to /content/tfs/us/en/test-folder/products/T.html in BundledScriptServlet (/libs/sling/servlet/errorhandler/404.jsp)

Avatar

Correct answer by
Community Advisor

Hi @Aaron_Dempwolff 
The rewrite rule shared as sample. you need to write your own based on content taxonomy.

For example if Product path are at 

/content/tfs/us/en/test-folder/products/T.html

then 

#Example product redirect
^/content/tfs/([a-zA-Z]{2})/([a-zA-Z]{2})/test-folder/products/(.*) /content/tfs/$1/$2/test-folder/products.$3 [PT,L]

 



Arun Patidar

Avatar

Community Advisor

Hi @Aaron_Dempwolff 


I think as @AMANATH_ULLAH  highlighted, using Dispatcher Rewrite rules, you can achieve above use case but only on dispatcher.


If you want it to work internally in AEM and other environments , the best solution would be to use sling mapping
http://[host]:[port]/system/console/configMgr/org.apache.sling.jcr.resource.internal.JcrResourceReso...

In above configuration under URL Mappings you can create a mapping that routes requests like domain.com/products/product1 to the path.


You can take help of this blog : https://abhigyanswaroop.medium.com/resource-mapping-in-adobe-experience-manager-aem-1658653a683
to change mapping of resource.resolver.mapping value in above configuration.

Avatar

Level 4

I am already using the same feature in my current project. You need to use rewrite rules only.

 

 

RewriteRule ^/products/([A-Za-z0-9\-_]+)$ /content/siteName/us/en/products.$1.html [NC,PT,L]

 

 
This will convert the URL and AEM will receive the request with .selector. The same thing has been mentioned by Arun as well. But, you are testing on your local author instance ( Assumed from :4502 in the URL). Rewrite rules will not work on your author or publisher. You need to set up a dispatcher and then test this. Also, make sure you write a correct rewrite rule based on the hierarchy of pages in your project. 
 

Avatar

Administrator

@Aaron_Dempwolff Did you find the suggestions helpful? Please let us know if you require more information. Otherwise, please mark the answer as correct for posterity. If you've discovered a solution yourself, we would appreciate it if you could share it with the community. Thank you!



Kautuk Sahni