myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Paul Nicolucci (JIRA)" <>
Subject [jira] [Commented] (MYFACES-4138) Issue with some JSF Artifacts eligible for injection
Date Mon, 25 Sep 2017 19:43:00 GMT


Paul Nicolucci commented on MYFACES-4138:

Close as "not a problem"?

> Issue with some JSF Artifacts eligible for injection
> ----------------------------------------------------
>                 Key: MYFACES-4138
>                 URL:
>             Project: MyFaces Core
>          Issue Type: Bug
>    Affects Versions: 2.2.12, 2.3.0-beta
>            Reporter: Eduardo Breijo
> When we register an ActionListener or PhaseListener globally via faces-config.xml, the
instance that is created per listener is injectable, that is, we can do @Inject in the instance.
These listeners are added to the injected bean storage list in the application map and as
a result, we can call @PreDestroy and @PostConstruct on this scenario. 
> On the other hand, when facelet elements <f:actionListener/> and <f:phaseListener/>
are used, the instances that are created (per click for action listener or per view for phase
listener) are not injectable. That is, we cannot do @Inject inside of these objects. And @PreDestroy
and @PostConstruct are not invoked on them.
> I supposes we want to have the same behavior in both cases.
> To solve this issue, we can probably do a similar logic as what was done in FacesConfigurator
that we call inject on the instance, and then store that in the injected bean storage list.
We can add that logic in the ActionListenerHandler and PhaseListenerHandler classes after
the instance is created.
> // Code snippet
> instance = (ActionListener) ReflectionUtil.forName(this.type).newInstance();
> ExternalContext externalContext = faces.getExternalContext();
> // Note that we have to make INJECTED_BEAN_STORAGE_KEY public
> List<BeanEntry> injectedBeanStorage = (List<BeanEntry>)externalContext.getApplicationMap().get(FacesConfigurator.INJECTED_BEAN_STORAGE_KEY);

> InjectionProvider injectionProvider = InjectionProviderFactory.getInjectionProviderFactory(
>                                                             externalContext).getInjectionProvider(externalContext);
> Object creationMetaData = injectionProvider.inject(instance);
> injectedBeanStorage.add(new BeanEntry(instance, creationMetaData));
> injectionProvider.postConstruct(instance, creationMetaData);
> But there is an issue when adding that. Every time we use <f:actionListener/> with
type defined but no binding, a new instance is created on every button click, the same will
happen with <f:phaseListener/>. These instances are added to the list of injected bean
storage, and that reference will exist until app shuts down, creating a memory leak. So we
need a way to remove those references from the list once we are out of scope. We might need
a different list for this case.

This message was sent by Atlassian JIRA

View raw message