use of com.liferay.faces.bridge.bean.BeanManagerFactory in project liferay-faces-bridge-impl by liferay.
the class ManagedBeanScopePhaseListener method afterPhase.
@Override
public void afterPhase(PhaseEvent phaseEvent) {
if (phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE) {
FacesContext facesContext = phaseEvent.getFacesContext();
PortletPhase portletRequestPhase = BridgeUtil.getPortletRequestPhase(facesContext);
if ((portletRequestPhase == Bridge.PortletPhase.RENDER_PHASE) || (portletRequestPhase == Bridge.PortletPhase.RESOURCE_PHASE)) {
// Remove any managed-beans in request scope. According to the JSF 2.0 JavaDocs for {@link
// ExternalContext.getRequestMap}, before a managed-bean is removed from the map, any public no-argument
// void return methods annotated with javax.annotation.PreDestroy must be called first. Note that the
// bridge {@link RequestAttributeMap.remove(Object)} method will ensure that any @PreDestroy method(s)
// are called. The JavaDocs also state that this should only be the case for objects that are actually
// managed-beans.
ExternalContext externalContext = facesContext.getExternalContext();
Map<String, Object> requestScope = externalContext.getRequestMap();
List<String> managedBeanKeysToRemove = new ArrayList<String>();
Set<Map.Entry<String, Object>> mapEntries = requestScope.entrySet();
String appConfigAttrName = ApplicationConfig.class.getName();
Map<String, Object> applicationMap = externalContext.getApplicationMap();
ApplicationConfig applicationConfig = (ApplicationConfig) applicationMap.get(appConfigAttrName);
PortletContext portletContext = (PortletContext) externalContext.getContext();
BeanManagerFactory beanManagerFactory = (BeanManagerFactory) BridgeFactoryFinder.getFactory(portletContext, BeanManagerFactory.class);
BeanManager beanManager = beanManagerFactory.getBeanManager(applicationConfig.getFacesConfig());
for (Map.Entry<String, Object> mapEntry : mapEntries) {
String potentialManagedBeanName = mapEntry.getKey();
Object potentialManagedBeanValue = mapEntry.getValue();
// simply pass the attribute name.
if (beanManager.isManagedBean(potentialManagedBeanName, potentialManagedBeanValue)) {
managedBeanKeysToRemove.add(potentialManagedBeanName);
}
}
for (String managedBeanKey : managedBeanKeysToRemove) {
requestScope.remove(managedBeanKey);
}
}
}
}
use of com.liferay.faces.bridge.bean.BeanManagerFactory in project liferay-faces-bridge-impl by liferay.
the class BridgeSessionListener method sessionDestroyed.
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
if (firstInstance) {
// Discover Factories
BeanManagerFactory beanManagerFactory = null;
BridgeRequestScopeManagerFactory bridgeRequestScopeManagerFactory = null;
HttpSession httpSession = null;
ServletContext servletContext = null;
PortletContext portletContext = null;
try {
httpSession = httpSessionEvent.getSession();
servletContext = httpSession.getServletContext();
portletContext = new PortletContextAdapter(servletContext);
beanManagerFactory = (BeanManagerFactory) BridgeFactoryFinder.getFactory(portletContext, BeanManagerFactory.class);
bridgeRequestScopeManagerFactory = (BridgeRequestScopeManagerFactory) BridgeFactoryFinder.getFactory(portletContext, BridgeRequestScopeManagerFactory.class);
} catch (Exception e) {
String contextPath = "unknown";
if (servletContext != null) {
contextPath = servletContext.getContextPath();
}
logger.error("Unable to discover factories for contextPath=[{0}] possibly because the portlet never received a RenderRequest", contextPath);
}
if ((beanManagerFactory != null) && (bridgeRequestScopeManagerFactory != null)) {
// Cleanup instances of BridgeRequestScope that are associated with the expiring session.
BridgeRequestScopeManager bridgeRequestScopeManager = bridgeRequestScopeManagerFactory.getBridgeRequestScopeManager(portletContext);
bridgeRequestScopeManager.removeBridgeRequestScopesBySession(httpSession);
// For each session attribute:
String appConfigAttrName = ApplicationConfig.class.getName();
ApplicationConfig applicationConfig = (ApplicationConfig) servletContext.getAttribute(appConfigAttrName);
BeanManager beanManager = beanManagerFactory.getBeanManager(applicationConfig.getFacesConfig());
try {
Enumeration<String> attributeNames = httpSession.getAttributeNames();
while (attributeNames.hasMoreElements()) {
String attributeName = attributeNames.nextElement();
// is an attribute that was set using PortletSession.setAttribute(String, Object).
if ((attributeName != null) && attributeName.startsWith("javax.portlet.p.")) {
int pos = attributeName.indexOf("?");
if (pos > 0) {
Object attributeValue = httpSession.getAttribute(attributeName);
httpSession.removeAttribute(attributeName);
if (attributeValue != null) {
// one would get cleaned-up by Mojarra.
if (beanManager.isManagedBean(attributeName, attributeValue)) {
PreDestroyInvokerFactory preDestroyInvokerFactory = (PreDestroyInvokerFactory) BridgeFactoryFinder.getFactory(portletContext, PreDestroyInvokerFactory.class);
PreDestroyInvoker preDestroyInvoker = preDestroyInvokerFactory.getPreDestroyInvoker(servletContext);
preDestroyInvoker.invokeAnnotatedMethods(attributeValue, true);
} else // Otherwise,
{
// If the current session attribute is Mojarra-vendor-specific, then
String attributeValueClassName = attributeValue.getClass().getName();
if (attributeName.contains(MOJARRA_ACTIVE_VIEW_MAPS) || attributeValueClassName.contains(MOJARRA_PACKAGE_PREFIX)) {
// Rename the namespaced attribute by stripping off the standard portlet
// prefix. This will enable Mojarra's session expiration features to find
// attributes that it is expecting.
String nonPrefixedName = attributeName.substring(pos + 1);
logger.debug("Renaming Mojarra session attributeName=[{0}] -> [{1}]", attributeName, nonPrefixedName);
httpSession.setAttribute(nonPrefixedName, attributeValue);
// If this is the attribute that contains all of the active view maps, then
if (MOJARRA_ACTIVE_VIEW_MAPS.equals(nonPrefixedName)) {
if (mojarraAbleToCleanUpViewScopedDataAccessor.get(portletContext)) {
// Invoke the Mojarra
// ViewScopeManager.sessionDestroyed(HttpSessionEvent) method in
// order to cleanup the active view maps. Rather than waiting for
// the servlet container to call the method during session
// expiration, it is important to call it directly within this
// while-loop for two reasons: 1) If the developer did not
// explicitly specify the order of the Mojarra ConfigureListener and
// this BridgeSessionListener in WEB-IN/web.xml descriptor
// (FACES-1483) then there is no guarantee that the method would get
// called. 2) In the case of multiple portlet instances, each
// instance has its own namespaced attribute in the session.
// Renaming each namespaced attribute to
// "com.sun.faces.application.view.activeViewMaps" would only enable
// Mojarra to cleanup the last one.
HttpSessionListener viewScopeManager = (HttpSessionListener) servletContext.getAttribute(MOJARRA_VIEW_SCOPE_MANAGER);
if (viewScopeManager != null) {
try {
logger.debug("Asking Mojarra ViewScopeManager to cleanup @ViewScoped managed-beans");
viewScopeManager.sessionDestroyed(httpSessionEvent);
} catch (Exception e) {
logger.error(e);
}
}
}
}
}
}
}
}
}
}
} catch (IllegalStateException e) {
logger.warn("Server does not permit cleanup of Mojarra managed-beans during session expiration");
}
}
}
}
Aggregations