kwin commented on code in PR #106:
URL: https://github.com/apache/sling-site/pull/106#discussion_r1061127843
##########
src/main/jbake/content/documentation/bundles/models.md:
##########
@@ -179,92 +150,121 @@ Since Sling Models 1.2.0 there is another way of
instantiating models. The OSGi
// See the javadoc of the ModelFactory for which Exception can be
expected here
}
-In addition `ModelFactory` provides methods for checking whether a given class
is a model at all (having the model annotation) or whether a class can be
adapted from a given adaptable.
+In addition `ModelFactory` provides methods for checking whether a given class
is a model at all (having the model annotation) or whether a class can be
adapted from a given adaptable.
## Usage in HTL
-[Sling Models Use
Provider](/documentation/bundles/scripting/scripting-htl.html#java-use-provider-1)
(internally uses the `ModelFactory` from above).
+Please see [Sling Models Use
Provider](/documentation/bundles/scripting/scripting-htl.html#java-use-provider-1);
internally it uses the `ModelFactory` from above.
-# Other Options
-## Names
-If the field or method name doesn't exactly match the property name, `@Named`
can be used:
- ::java
- @Model(adaptables=Resource.class)
- public class MyModel {
-
- @Inject @Named("secondPropertyName")
- private String otherName;
- }
-
+# Available injectors
+
+In the above cases just the `@ValueMapValue` annotation was used, but there
other available injectors. For each injector there is a specialized annotation
available. For the optional parameters see the next section.
+
+
+Injector Name | Annotation | Supported Optional Elements |
Description | Array Support | Parametrized Type Support
Review Comment:
The first column is now a label and no longer the name. The name should
still be documented as it must be used with annotation `@Source`
##########
src/main/jbake/content/documentation/bundles/models.md:
##########
@@ -89,40 +83,13 @@ Constructor injection is also supported (as of Sling Models
1.1.0):
Because the name of a constructor argument parameter cannot be detected via
the Java Reflection API a `@Named` annotation is mandatory for injectors that
require a name for resolving the injection.
-Constructors may use any visibility modifier (as of [Sling Models
1.5.0](https://issues.apache.org/jira/browse/SLING-8069)):
+Constructors may use any visibility modifier (as of [Sling Models
1.5.0](https://issues.apache.org/jira/browse/SLING-8069)).
- ::java
- @Model(adaptables=Resource.class)
- public class PublicConstructorModel {
- @Inject
- public PublicConstructorModel() {
- // constructor code
- }
- }
+## @Model and adaptable types
- @Model(adaptables=Resource.class)
- public class ProtectedConstructorModel {
- @Inject
- protected ProtectedConstructorModel() {
- // constructor code
- }
- }
+While technically it is possible to provide any class implementing the
`Adaptable` interface as the `adaptable` parameter to the `@Model` annotation,
the Sling Model Framework and the default injectors is mostly built under the
assumption that the adaption is done from a Sling Resource. All injectors also
support adaption from a `SlingHttpServletRequest` object, but normally this is
then converted into a adaption of the resource of the request. The only
exception on the default injectors is the "Request Attribute" injector, which
requires that the model is adapted from a SlingHttpServletRequest.
Review Comment:
More prominent examples requiring request: script bindings and sling object
##########
src/main/jbake/content/documentation/bundles/models.md:
##########
@@ -660,86 +612,78 @@ If you want to generate a bundle header compliant with
Sling Models < 1.3.4 (i.e
</instructions>
</configuration>
-# Caching
-By default, Sling Models do not do any caching of the adaptation result and
every request for a model class will
-result in a new instance of the model class. However, there are two notable
cases when the adaptation result can be cached. The first case is when the
adaptable extends the `SlingAdaptable` base class. Most significantly, this is
the case for many `Resource` adaptables as `AbstractResource` extends
`SlingAdaptable`. `SlingAdaptable` implements a caching mechanism such that
multiple invocations of `adaptTo()` will return the same object. For example:
- ::java
- // assume that resource is an instance of some subclass of AbstractResource
- ModelClass object1 = resource.adaptTo(ModelClass.class); // creates new
instance of ModelClass
- ModelClass object2 = resource.adaptTo(ModelClass.class); // SlingAdaptable
returns the cached instance
- assert object1 == object2;
-While this is true for `AbstractResource` subclasses, it is notably **not**
the case for `SlingHttpServletRequest` as this class does not extend
`SlingAdaptable`. So:
- ::java
- // assume that request is some SlingHttpServletRequest object
- ModelClass object1 = request.adaptTo(ModelClass.class); // creates new
instance of ModelClass
- ModelClass object2 = request.adaptTo(ModelClass.class); // creates another
new instance of ModelClass
- assert object1 != object2;
+# Discouraged annotations
-Since API version 1.3.4, Sling Models *can* cache an adaptation result,
regardless of the adaptable by specifying `cache = true` on the `@Model`
annotation.
+In earlier versions of Sling Models the use of the annotation `@Inject` was
suggested and documented; but over time it turned out that it had 2 major
issues:
+* This injection iterated through all available injectors and injected the
first non-null value provided by an injector. This lead to unpredictable
behavior, although the order is well-defined. The addition of the `@Source`
annotation did not really help.
Review Comment:
Although @Source would have helped it was rarely used.
##########
src/main/jbake/content/documentation/bundles/models.md:
##########
@@ -660,86 +612,78 @@ If you want to generate a bundle header compliant with
Sling Models < 1.3.4 (i.e
</instructions>
</configuration>
-# Caching
-By default, Sling Models do not do any caching of the adaptation result and
every request for a model class will
-result in a new instance of the model class. However, there are two notable
cases when the adaptation result can be cached. The first case is when the
adaptable extends the `SlingAdaptable` base class. Most significantly, this is
the case for many `Resource` adaptables as `AbstractResource` extends
`SlingAdaptable`. `SlingAdaptable` implements a caching mechanism such that
multiple invocations of `adaptTo()` will return the same object. For example:
- ::java
- // assume that resource is an instance of some subclass of AbstractResource
- ModelClass object1 = resource.adaptTo(ModelClass.class); // creates new
instance of ModelClass
- ModelClass object2 = resource.adaptTo(ModelClass.class); // SlingAdaptable
returns the cached instance
- assert object1 == object2;
-While this is true for `AbstractResource` subclasses, it is notably **not**
the case for `SlingHttpServletRequest` as this class does not extend
`SlingAdaptable`. So:
- ::java
- // assume that request is some SlingHttpServletRequest object
- ModelClass object1 = request.adaptTo(ModelClass.class); // creates new
instance of ModelClass
- ModelClass object2 = request.adaptTo(ModelClass.class); // creates another
new instance of ModelClass
- assert object1 != object2;
+# Discouraged annotations
-Since API version 1.3.4, Sling Models *can* cache an adaptation result,
regardless of the adaptable by specifying `cache = true` on the `@Model`
annotation.
+In earlier versions of Sling Models the use of the annotation `@Inject` was
suggested and documented; but over time it turned out that it had 2 major
issues:
+* This injection iterated through all available injectors and injected the
first non-null value provided by an injector. This lead to unpredictable
behavior, although the order is well-defined. The addition of the `@Source`
annotation did not really help.
+* This iteration turned out to the performance bottleneck, especially if
(optional) injections were not succesful, and then all other injectors have to
be tried.
Review Comment:
turned out to be a performance bottleneck
##########
src/main/jbake/content/documentation/bundles/models.md:
##########
@@ -179,92 +150,121 @@ Since Sling Models 1.2.0 there is another way of
instantiating models. The OSGi
// See the javadoc of the ModelFactory for which Exception can be
expected here
}
-In addition `ModelFactory` provides methods for checking whether a given class
is a model at all (having the model annotation) or whether a class can be
adapted from a given adaptable.
+In addition `ModelFactory` provides methods for checking whether a given class
is a model at all (having the model annotation) or whether a class can be
adapted from a given adaptable.
## Usage in HTL
-[Sling Models Use
Provider](/documentation/bundles/scripting/scripting-htl.html#java-use-provider-1)
(internally uses the `ModelFactory` from above).
+Please see [Sling Models Use
Provider](/documentation/bundles/scripting/scripting-htl.html#java-use-provider-1);
internally it uses the `ModelFactory` from above.
-# Other Options
-## Names
-If the field or method name doesn't exactly match the property name, `@Named`
can be used:
- ::java
- @Model(adaptables=Resource.class)
- public class MyModel {
-
- @Inject @Named("secondPropertyName")
- private String otherName;
- }
-
+# Available injectors
+
+In the above cases just the `@ValueMapValue` annotation was used, but there
other available injectors. For each injector there is a specialized annotation
available. For the optional parameters see the next section.
+
+
+Injector Name | Annotation | Supported Optional Elements |
Description | Array Support | Parametrized Type Support
+----- | ----------------- | ------------------------------
|------------------------- | --------------- | ---------------------------
+Scripting Bindings|`@ScriptVariable` | `injectionStrategy` and `name`
| Injects the script variable defined via [Sling
Bindings](https://cwiki.apache.org/confluence/display/SLING/Scripting+variables).
If `name` is not set the name is derived from the method/field name. | no
conversion is done | If a parameterized type is passed, the bindings value
must be of a compatible type of the parameterized type.
+ValueMap | `@ValueMapValue` | `injectionStrategy`, `name` | Injects a
`ValueMap` value taken from the adapted resource (either taking from the
adapted resource or the resource of the adapted SlingHttpServletRequest). If
`name` is not set the name is derived from the method/field name. | Primitive
arrays wrapped/unwrapped as necessary. Wrapper object arrays are
unwrapped/wrapped as necessary. | Parameterized `List` and `Collection`
injection points are injected by getting an array of the component type and
creating an unmodifiable `List` from the array.
+Child Resource | `@ChildResource` | `injectionStrategy`, `name` | Injects
a child resource by name (taken from the adapted resource (either taking from
the adapted resource or the resource of the adapted SlingHttpServletRequest).
If `name` is not set the name is derived from the method/field name. | none |
if a parameterized type `List` or `Collection` is passed, a `List<Resource>` is
returned (the contents of which may be adapted to the target type) filled with
all child resources of the resource looked up by the given name.
+Request Attribute | `@RequestAttribute` | `injectionStrategy`, `name` |
Injects a request attribute by name, it requires the the adaptable is a
`SlingHttpServletRequest` . If `name` is not set the name is derived from the
method/field name. | no conversion is done | If a parameterized type is passed,
the request attribute must be of a compatible type of the parameterized type.
+Resource path | `@ResourcePath` | `injectionStrategy`, `path`, and `name`
|Injects a resource either by path or by reading a property with the given
name. | yes | none
+OSGi service | `@OSGiService` | `injectionStrategy`, `filter` |
Injects an OSGi service by type (and the optional filter) | yes | Parameterized
`List` and `Collection` injection points are injected by getting an array of
the services and creating an unmodifiable `List` from the array.
+Context-Aware Configuration | `@ContextAwareConfiguration` |
`injectionStrategy`, `name` | Lookup context-aware configuration. See
[Context-Aware Configuration](#context-aware-configuration) below. | yes | If a
parameterized type `List` or `Collection` is used, a configuration collection
is looked up.
+Self | `@Self` | `injectionStrategy` |
Injects the adaptable itself. If the field type does not match with the
adaptable it is tried to adapt the adaptable to the requested type. | none |
none
+Sling Object | `@SlingObject` | `injectionStrategy` |
Injects commonly used sling objects if the field matches with the class:
request, response, resource resolver, current resource, SlingScriptHelper |
none | none
+
+# Parameters to the Injectors
+
+Injectors can support optional parameters as listed in the above table
+
## Optional and Required
-`@Inject`ed fields/methods are assumed to be required. To mark them as
optional, use `@Optional`:
- ::java
- @Model(adaptables=Resource.class)
- public class MyModel {
-
- @Inject @Optional
- private String otherName;
- }
+Injected fields/methods are assumed to be required. To mark them as optional,
there are 2 options:
+
+* add the parameter `injectionStrategy=InjectionStrategy.OPTIONAL` to the
annotation
+* or wrap the type into an `Optional`
+
+It is recommended to use the approach using the `Optional` type, because then
this "optionality" is also expressed in the type system.
+
+ ::java
+ import java.util.Optional;
+
+ @Model(adaptables=Resource.class)
+ public class MyModel {
+
+ @ValueMapValue(injectionStrategy=InjectionStrategy.OPTIONAL)
+ private String optionalProperty;
+
+ @ValueMapValue
+ private Optional<String> anotherOptionalProperty;
+ }
+Please note, that also injections marked as optional are always tried. It is
just that any failure to inject a value does not lead to the termination of the
creation of the SlingModel, but instead it continues, leaving the field
value/return value at the default value of the used type.
Review Comment:
that even injections marked as
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]