Hi Jason,
I'm all for anything that could make injector development simpler. But
personally, that looks like a weird usage for annotations. Have you
considered using the Builder pattern?
Maybe an interface like this:
public interface InjectorFactory {
Injector build(InjectorBuilder builder);
}
And then you would have:
@Component @Service
public class RequestAttributeInjectorFactory {
public Injector build(InjectorBuilder builder) {
return
builder.withName("request-attributes").withAdaptable(ServletRequest.class).withMethod("getAttribute").build();
}
}
This, IMHO, accomplishes the same goal, but somehow looks less
"magical" :) WDYT?
As I wrote yesterday in a separate thread, I do think there's been a
bit of sloppiness on my part about type checking/conversion. Unless
specifically required (i.e. the case of the ValueMapInjector), all
type checking and conversion should happen in the ModelAdapterFactory.
And really all conversion should happen via adaptTo().
Justin
On Thu, Aug 28, 2014 at 2:49 PM, Jason Bailey <[email protected]> wrote:
> Our team has been working on adopting the sling model paradigm which has
> given me a chance to get involved with creating a number of injectors to meet
> our needs.
>
> I wanted to share some of my observations.
> To clarify the existing flow, when we are looking at performing an injection
> it is really a three step process.
>
> * Obtain the base Object from the supplied adaptable
> * Retrieve a value from the base Object
> * Manipulate the value to meet the type expectations of the annotated field
>
> During any one of these steps, the result of the step could equal null and
> the process would then move on to the next injector.
> While working on these injectors I came across a series of commonalities
> within their implementations. You could actually define a shorthand for the
> majority of the injectors, and extrapolating from that you could define an
> injector completely in annotations.
>
> Example annotations derived from existing
>
> For defining the base object
> @adaptable(Class<?>) The expected object to be used as the source of this
> injector
> @via(String) use a JavaBean property of the adaptable as the source of the
> injection
> @viaArgument(Object*) if present, use this as the argument for the @via access
> @adaptTo(Class<?>) if present attempts to adapt the current base Object
>
> For retrieving the value
> @method(String) name of the method to use.
> @named(String) name of the argument for the above @method, defaults to the
> property name
> @default(Object*) replaces the returned value if null.
>
> Which, if you put the logic for these annotations in the framework, would
> allow you to do things like this mockup of a RequestAttribute injector:
>
> public class RequestAttributeInjector {
>
> @adaptable(ServletRequest.class) @method("getAttribute")
> Object getValue(Object adaptable, String name, Type declaredType,
> AnnotatedElement element, DisposalCallbackRegistry callbackRegistry){
> return adaptable;
> }
> }
>
> where a SlingBindings injector would look like this
>
> public class SlingBindingsInjector {
>
> @adaptable(ServletRequest.class) @via("attribute")
> @viaArgument(SlingBindings.class.name()) @method("get")
> Object getValue(Object adaptable, String name, Type declaredType,
> AnnotatedElement element, DisposalCallbackRegistry callbackRegistry){
> return adaptable;
> }
>
> }
>
> You'll notice I didn't touch step 3. Because once you extract these concepts
> into separate steps, type conversion is the same for all objects and
> therefore something that should be supplied by the framework. This sort of
> separation would provide consistency of type conversion across different
> injectors.
>
> My TL;DR comes down to
> I believe that by adding additional meta information to the sling injector
> definition, either through annotations or properties, that you could
> streamline the functionality and make it easier to develop new injectors. An
> example being the declaration of what type of adaptable is expected and
> verifying that prior to calling the injector.
>
> The addition of the meta information could be added expanded to the point
> that most injectors could be defined as a series of properties.
>
> Additionally, unifying the type conversion outside of the injector would be
> beneficial, as it provides a consistent type conversion process and enables
> improvements of that process to be shared by all injectors.
>
> WDYT?
>
> -Jason