Expand my Community achievements bar.

SOLVED

how does sling field injection work?

Avatar

Level 2

Hi, 

I was going through this article https://sling.apache.org/documentation/bundles/models.html#field-injection to understand models in aem.

How does the injection of values really work?  The documentation says that : In this case, a property named propertyName will be looked up from the Resource (after first adapting it to a ValueMap) and it is injected. Fields can use any visibility modifier:

 

So does the resource first adapted to ValueMap and then injected?

if anyone has any detailed explanation or understanding of what happens behind the scene, could you please explain?

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @sindhusr 

The resource is first adapted to a `ValueMap` and then injected into the model class. Here's a more detailed explanation of what happens behind the scenes:

When a model class is instantiated, Sling creates a new instance of the class and injects the values of its fields using the `@Inject` annotation. The injection process works as follows:

1. Sling looks up the resource that corresponds to the model instance. This is typically done using the `@Self` annotation, which tells Sling to inject the resource that corresponds to the model instance.

2. Sling adapts the resource to a `ValueMap`. A `ValueMap` is a map-like interface that provides access to the properties of a resource.

3. Sling looks for fields in the model class that are annotated with `@Inject` and have a name that matches a property in the `ValueMap`. For example, if a field is named `propertyName` and there is a property in the `ValueMap` with the same name, Sling will inject the value of that property into the field.

4. If the field is of a different type than the property in the `ValueMap`, Sling will attempt to convert the property to the appropriate type. For example, if the field is of type `int` and the property in the `ValueMap` is a string, Sling will attempt to convert the string to an integer.

5. If there is no property in the `ValueMap` that matches the name of the field, Sling will not inject a value into the field.

6. If the field is not annotated with `@Inject`, Sling will not inject a value into the field.

So, to answer your question, yes, the resource is first adapted to a `ValueMap` and then injected into the model class. This allows the model class to access the properties of the resource using a simple field-based syntax.

Thanks.



View solution in original post

4 Replies

Avatar

Level 4

Hello @sindhusr 

 

Apache Sling Models allow you to map resource properties, OSGi services, Sling objects and more onto Java POJOs, leveraging annotation-driven injection.

In the process of field injection in Sling Models, yes, the Resource is indeed first adapted to a ValueMap and then the designated property is injected.

Sling Models Works like this:

  1. A request arrives at the Sling instance for a specific resource.
  2. Based on the resource type, it is determined if a Sling model is associated with it.
  3. If a Sling model is linked, a new instance of that model class is created.
  4. For each field in the model class that has an injecting annotation (@Inject, @ValueMapValue, @OSGiService, etc.), Sling model implementation starts a look-up process:
    • If @ValueMapValue is used, it takes the Resource related with the current request, adapts it into a ValueMap, and looks for a property in that ValueMap which corresponds to the field (or the name defined in @Named annotation, if present).
    • If it finds the property in the ValueMap, it performs type conversion (if necessary), and then sets the field with that value.
    • When the property isn't found in the ValueMap (or its value is null), it checks if the @Optional annotation is present for the field. If it's not, an exception is thrown.

Thanks,

Venkat

Avatar

Community Advisor

@sindhusr 

 

The entire sequence unfolds as follows:

  1. Upon receiving a request, the Sling Framework selects a Sling Model corresponding to the resource.
  2. A new instance of the chosen model, such as new MyModel(), is generated by Sling through the adaptation of the current resource.
  3. Sling then fulfills all declared dependencies utilizing annotations like @Inject, @ValueMapValue, @OSGiService, among others.
    • To fetch value from a Resource, ValueMap is retrieved from Resource and then the @ValueMapValue annotations can readily use it to Inject the required fields.
  4. Subsequently, Sling executes the method annotated with @PostConstruct.

Reference: https://techrevelhub.wordpress.com/2017/03/18/sling-model-annotations/#PostConstruct 

 

To understand Adapter Pattern in detail, please refer to https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/implementing/develo... 


Aanchal Sikka

Avatar

Correct answer by
Community Advisor

Hi @sindhusr 

The resource is first adapted to a `ValueMap` and then injected into the model class. Here's a more detailed explanation of what happens behind the scenes:

When a model class is instantiated, Sling creates a new instance of the class and injects the values of its fields using the `@Inject` annotation. The injection process works as follows:

1. Sling looks up the resource that corresponds to the model instance. This is typically done using the `@Self` annotation, which tells Sling to inject the resource that corresponds to the model instance.

2. Sling adapts the resource to a `ValueMap`. A `ValueMap` is a map-like interface that provides access to the properties of a resource.

3. Sling looks for fields in the model class that are annotated with `@Inject` and have a name that matches a property in the `ValueMap`. For example, if a field is named `propertyName` and there is a property in the `ValueMap` with the same name, Sling will inject the value of that property into the field.

4. If the field is of a different type than the property in the `ValueMap`, Sling will attempt to convert the property to the appropriate type. For example, if the field is of type `int` and the property in the `ValueMap` is a string, Sling will attempt to convert the string to an integer.

5. If there is no property in the `ValueMap` that matches the name of the field, Sling will not inject a value into the field.

6. If the field is not annotated with `@Inject`, Sling will not inject a value into the field.

So, to answer your question, yes, the resource is first adapted to a `ValueMap` and then injected into the model class. This allows the model class to access the properties of the resource using a simple field-based syntax.

Thanks.



Avatar

Administrator

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