Expand my Community achievements bar.

SOLVED

Usage of @Via in sling models

Avatar

Level 3

I understand from the documentation, that @Via is used to inject objects not available through the adaptable mapped to the model

In that case, if my adaptable is Resource.class and I have to inject SlingHttpServletRequset or SlingHttpServletResponse. I will have to use @Inject @Via to fetch it from SlingHttpServletRequest adaptable?

In that case, what is the parameter I have to pass to @Via?

In case of resource, it will be @Via ("resource") - what will it be for slingRequest?

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Nitik,

  Let me try to explain you what I understand here . Let us take the simple example from what documentation Scott has shared

  - So this says ; when the model's adaptable is SlingHttpServletRequest , then when you try to inject getPropertyName() ; it will be return the property via resource method of the SlingHttpServletRequest object "request" like the below

request.getResource().getValueMap().get("propertyName", String.class)

That said , if you check the API SlingHttpServletRequest (Apache Sling Aggregate 5-incubator API)  you can understand that a resource can be fetched from a request , but the vice versa is not possible .

    So basically that means inject the value via resource API in SlingHttpServletRequest API.

  I am not aware of a way to get a request object from a resource and hence I don't believe something like below is even possible

@Model(adaptables=Resource.class)

public class MyModel

    @Inject

    @Via("request")

    private String someObj;

}

For further reading the below section explains what all standard types are provided via while and how it is implemented

Apache Sling :: Sling Models

The other thing you can do is to adapt the SlingHttpServletRequest and get the resource from it

@Model(adaptables = SlingHttpServletRequest.class)

public class MyModel {

  

     @Inject

     SlingHttpServletRequest request;

     @PostConstruct

     protected void init() {

         Resource resource = request.getResource() ;

     }

}

View solution in original post

25 Replies

Avatar

Level 10

Here is a much better example to extend a Core Component - we will make a HELPX article -- use this to extend the Title COMPONENT. Notice here - they are not even using @Via

package com.adobe.community.core.models;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;

import org.apache.sling.api.SlingHttpServletRequest;

import org.apache.sling.models.annotations.Model;

import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;

import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;

import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import com.adobe.cq.wcm.core.components.models.Title;

import com.day.cq.commons.jcr.JcrConstants;

import com.day.cq.wcm.api.Page;

import com.day.cq.wcm.api.designer.Style;

@Model(resourceType = "/apps/ExtendCore/components/content/title",

    adaptables = SlingHttpServletRequest.class,

    adapters = Title.class)

public class MyCustomTitleImpl implements Title {

    @ScriptVariable

    private Page currentPage;

    @ScriptVariable

    private Style currentStyle;

    @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = JcrConstants.JCR_TITLE)

    private String title;

    @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL)

    private String type;

    /**

     * The {@link Heading} object for the type of this title.

     */

    private Heading heading;

    @PostConstruct

    private void initModel() {

        if (StringUtils.isBlank(title)) {

            title = StringUtils.defaultIfEmpty(currentPage.getPageTitle(), currentPage.getTitle());

        }

        if (heading == null) {

            heading = Heading.getHeading(type);

            if (heading == null) {

                heading = Heading.getHeading(currentStyle.get(PN_DESIGN_DEFAULT_TYPE, String.class));

            }

        }

    }

    @Override

    public String getText() {

        return "My Project - " + title;

    }

    @Override

    public String getType() {

        if (heading != null) {

            return heading.getElement();

        }

        return null;

    }

    private enum Heading {

        H1("h1"),

        H2("h2"),

        H3("h3"),

        H4("h4"),

        H5("h5"),

        H6("h6");

        private String element;

        Heading(String element) {

            this.element = element;

        }

        private static Heading getHeading(String value) {

            for (Heading heading : values()) {

                if (StringUtils.equalsIgnoreCase(heading.element, value)) {

                    return heading;

                }

            }

            return null;

        }

        public String getElement() {

            return element;

        }

    }

}

Avatar

Level 10

For anyone reading this thread and want to know how to extend a Core Component - see this HELPX article -- Extending Adobe Experience Manager Core Components

Avatar

Level 4

Thanks Sam.

In helpx example, we are just using core title contract and then implementing the logic. In order to extend existing title implementation, what is recommended approach? Should we extended core implementation class or should we use @Via.

Avatar

Level 10

The doc example is wrong - the new HELPX artilce - follow it to learn how to extend core components - the Java part. You have to extend it as shown in the artilce. We are going to fix the example in the docs too to point to this new article. Ratna Kumar is currently testing this article.

Avatar

Level 1

Yes, I tested this article and it works!! Below is the screenshot.

Title.PNG

dialog.PNG

Hope this helps!!

Thanks,

Ratna Kumar.