Re: JSF 2.3 Table 5-3 JSF artifacts eligible for injection - Constructor Injection question


 

Hello Paul,

I secured some time to think about this today. If you like, you can
skip right to the CONCLUSION by searching for CONCLUSION:.

First, the general rationale for ctor injection is adequately described
in this stackoverflow post
https://stackoverflow.com/questions/19381846/why-use-constructor-over-setter-injection-in-cdi .
Given that rationale, ctor injection seems to make the most sense for
domain objects, rather than the classes in Table 5-3.

Let's take a look at each of the classes in Table 5-3 and ask ourselves
if it makes sense to have ctor injection for that class, and what it
would mean to have ctor injection. I will also suggest a potential use
for ctor injection for a future revision of JSF.

javax.el.ELResolver

Section 5.5.2.1 states "ELResolver instances have application lifetime
and scope." Since this is lifetime scope, we really don't know what
would make sense to pass to a ctor injection.

Future: Perhaps the presence of @Inject with an ELResolver argument
could be used to provide a reference to the parent ELResolver in the
chain.

javax.faces.application.ApplicationFactory

Section 7.2 states, "A single instance of
javax.faces.application.ApplicationFactory must be made available to
each JSF- based web application running in a servlet or portlet
container." Since this is a singleton, what would make sense to pass to
the ctor?

Also, this class is mentioned in section 11.4.7 Delegating
Implementation Support. In that section, the spec says, "For all of
these artifacts, the decorator design pattern is leveraged, so that if
one provides a constructor that takes a single argument of the
appropriate type, the custom implementation receives a reference to
the implementation that was previously fulfilling the role." So in
this sense we already support ctor injection for this class. Future
occurrences of this explanation will be labeled as "See 11.4.7
Delegating Implementation Support"

Future: Perhaps this @Inject could be passed the
javax.enterprise.inject.spi.CDI.

javax.faces.application.NavigationHandler

Section 7.4.1 states, "A single NavigationHandler instance is
responsible for consuming the logical outcome returned by an application
action that was invoked, along with additional state information that is
available from the FacesContext instance for the current request, and
(optionally) selecting a new view to be rendered." So, this is a singleton.

See 11.4.7 Delegating Implementation Support

javax.faces.application.ResourceHandler

This is also an application singleton. See 11.4.7 Delegating
Implementation Support.

See 11.4.7 Delegating Implementation Support

Future: Perhaps this @Inject could be passed the default
ViewDeclarationLanguage?

javax.faces.application.StateManager

Section 7.8 makes it clear the StateManager is an application
singleton, therefore ctor injection doesn't make a lot of sense.

See 11.4.7 Delegating Implementation Support

Future: Perhaps this @Inject could be passed the default
ViewDeclarationLanguage?

javax.faces.component.visit.VisitContextFactory

This is a singleton factory. I don't see what it would be useful to
pass for ctor injection.

See 11.4.7 Delegating Implementation Support

javax.faces.context.ExceptionHandlerFactory

This is a singleton factory. I don't see what it would be useful to
pass for ctor injection.

See 11.4.7 Delegating Implementation Support

javax.faces.context.ExternalContextFactory

Section 6.8 states, "A single instance of
javax.faces.context.ExternalContextFactory must be made available to
each JSF-based web application running in a servlet or portlet
container."

This is a singleton factory. I don't see what it would be useful to
pass for ctor injection.

See 11.4.7 Delegating Implementation Support

javax.faces.context.FacesContextFactory

This is a singleton factory.

Future: Since the default one simply turns around and calls the
exceptionHandlerFactory() and externalContextFactory, it would make
sense to allow these to be @Inject ctor injected, but that would be a
new feature.

See 11.4.7 Delegating Implementation Support

javax.faces.context.PartialViewContextFactory

Since this is an application singletion, I don't know it would make
sense to pass for ctor injection.

javax.faces.event.ActionListener

See 11.4.7 Delegating Implementation Support

javax.faces.event.SystemEventListener

This one is implemented by application code.

Future: Perhaps ctor injection could be passed the Application?

javax.faces.lifecycle.ClientWindowFactory

This is a singleton factory.

Future: the default impl gets a handle to the Application and
subscribes to the PostConstructApplicationEvent. Perhaps ctor
injection could be useful to pass the Application.

javax.faces.lifecycle.LifecycleFactory

This is a singleton factory.

Future: Perhaps this @Inject could be passed the
javax.enterprise.inject.spi.CDI.

See 11.4.7 Delegating Implementation Support

javax.faces.event.PhaseListener

These are application singletons.

Future: Perhaps ctor injection could pass a reference to the
Application, or the Lifecycle?

javax.faces.render.RenderKitFactory

This is a singleton factory.

Future: Perhaps ctor injection could pass a reference to the
Application.

See 11.4.7 Delegating Implementation Support

javax.faces.view.ViewDeclarationLanguageFactory

This is a singleton factory.

Future: Perhaps ctor injection could pass a reference to the
Application.

javax.faces.view.facelets.FaceletCacheFactory

This is a singleton factory.

Future: Perhaps ctor injection could pass a reference to the
Application.

javax.faces.view.facelets. TagHandlerDelegateFactory

This is a singleton factory.

Future: Perhaps ctor injection could pass a reference to the
Application.

CONCLUSION:

In conclusion I will propose the JSF maintenance lead to make the
following change to the spec.

In section 5.4.1, please change the text

In addition to managed beans being injectable in this manner, the
following JSF artifacts are also injectable.

to be instead

In addition to managed beans being injectable in this manner, the
following JSF artifacts are also injectable via field and setter
injection. Constructor injection does not make sense for these
artifacts and is not supported.

Thanks,

Ed

Join jsf-spec@javaee.groups.io to automatically receive all group messages.