How to create URLS to read information from a content fragment? | Community
Skip to main content
Level 4
September 7, 2024
Solved

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

  • September 7, 2024
  • 4 replies
  • 1491 views

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
}
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 arunpatidar

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


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



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)


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]

 

4 replies

AMANATH_ULLAH
Community Advisor
Community Advisor
September 8, 2024

@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)

 

 

Amanath Ullah
arunpatidar
Community Advisor
Community Advisor
September 9, 2024

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

 

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

 

Arun Patidar
Level 4
September 9, 2024

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


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



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)

pulkitvashisth
Community Advisor
Community Advisor
September 8, 2024

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.JcrResourceResolverFactoryImpl

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.

Ankan_Ghosh
Level 3
September 10, 2024

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. 
 
kautuk_sahni
Community Manager
Community Manager
September 13, 2024

@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