How can I get all view scope managed beans for the current ViewRoot? - jsf

I have to implement some bean post processor for all view scope managed beans on the page. I have implemented SystemEventListener with PostConstructViewMapEvent as system-event-class. How can I get all view scope managed beans for the current ViewRoot? viewRoot.getViewMap() returns empty map (Mojarra JSF 2.1.19), but I have a few managed beans with view scope. Of course I can invoke my post processor in #PostConstruct method in every such bean, but is there a global solution like in Spring Framework?
My faces-config.xml configuration:
<application>
<system-event-listener>
<system-event-listener-class>com.myapplicationname.ViewScopeBeanPostProcessor</system-event-listener-class>
<system-event-class>javax.faces.event.PostConstructViewMapEvent</system-event-class>
<source-class>javax.faces.component.UIViewRoot</source-class>
</system-event-listener>
</application>

Related

Why is a CDI Managed Bean in faces-config.xml not registered as an obersver?

I have implemented a CDI Bean which is observing events from another bean:
#SessionScoped
public class FixedItemController implements Serializable {
....
public void onWorkflowEvent(#Observes WorkflowEvent workflowEvent) throws AccessDeniedException {
logger.info("evaluate event...");
....
}
....
}
This works fine as long as I am using the bean in a JSF page with its default name 'fixedItemController'.
But if I declare another instance of that bean in the faces-config.xml like this:
<managed-bean>
<managed-bean-name>myOrderItemController</managed-bean-name>
<managed-bean-class>org.imixs.marty.workflow.FixedItemController</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>childItemProperty</property-name>
<property-class>java.lang.String</property-class>
<value>_orderItems</value>
</managed-property>
</managed-bean>
the second instance (myOrderItemController) is not registered automatically as an observer for my WorkflowEvent.
What can I do, to ensure that my second instance - declared by the faces-config.xml - will be immediately instantiated and registered as an observer to my workitemEvent?
faces-config.xml does not register CDI managed beans. It registers JSF managed beans. Effectively, your #{myOrderItemController} is a JSF managed bean. It's like as if you use #ManagedBean instead of #Named. The JSF bean management facility does not scan for CDI specific #Observes annotation.
Keep it a CDI managed bean. Whatever you tried to solve for which you thought that registering it in faces-config.xml would be the right solution has to be solved differently using the CDI API instead of the JSF API.

How to get application scoped managed bean on servlet

I have a bean that I configured to be application scoped in faces-config.xml as below:
<managed-bean eager="true">
<managed-bean-name>communicationCRCList</managed-bean-name>
<managed-bean-class>com.ingdirect.edeal.bean.CommunicationCRCListBean</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
That been is loaded when the app starts by the call of the INIT() method on a different class.
The app starts, the class is loaded and create the bean calling the init method.
As it's an application scoped bean, it should be accessible from everywhere.
In my case, I would like to get that bean in a servlet. I read that all the application scoped managed beans are loaded in the servletContext. In order to get that bean, I tried the following in my servlet:
CommunicationCRCListBean CommunicationCrcListBean = (CommunicationCRCListBean) getServletContext().getAttribute(COMMUNICATION_LIST_CRC_BEAN);
For information, COMMUNICATION_LIST_CRC_BEAN = communicationCRCList--> name of the bean. Unfortunatly, I get null....
I can't figure out what's wrong... Does somebody has an idea ?

How to initialise a Managed Bean in request scope from a servlet

I have a servlet that will navigate to a JSF page upon some conditions using ExternalContext.redirect.
I need to initialise a Managed Bean in this Servlet and set it in request scope so that my JSF page can directly access the Managed Bean's property and display them on the page load.
I had seen posts that sets the bean using getServletContext()
Like,
getServletContext().setAttribute("beanName",new Bean())
it works.But this approach will be setting the bean in application scope instead of request scope.
Also i tried the following:
request.setAttribute("beanName",new Bean())
it doesnt work
So pls let me know if there is any way to set /initialise a managed bean in a request scope
If it's a request scoped bean, use HttpServletRequest#setAttribute()
BeanName beanName = new BeanName();
request.setAttribute("beanName", beanName);
If its a session scoped bean,
request.getSession().setAttribute("beanName", beanName);

Injecting EJB3.0 Beans into JSF2.0 Backing Beans... Impossible?

I'm working on a JSF project on Weblogic 11g, and our initial design is calling for JSF Backing Beans to invoke EJB3.0 beans to perform business logic and data access calls. The #EJB annotation doesn't seem to work in my project when I try to inject the EJB reference to the backing bean. Whenever I hit the class that I am testing, the constructor for my EJB is never called and I end up with a NPE. Is it possible to inject an EJB3.0 bean into a JSF backing bean? Is there another way I should be invoking an EJB through the JSF Backing bean? What is the best practice?
I googled somewhat and this indeed seems to be a known issue with Weblogic. Lot of similar topics are kept unanswered.
I found this blog which confirms that #EJB in Weblogic only works for resources definied by web.xml, not for JSF. The blog describes also in detail a workaround using ServletContextListener which is IMO not much better than using JNDI.
I also found this OTN topic which confirms that #EJB in Weblogic started to work when EJB modules are not included in subdirectories (see the answer posted at the bottom, Feb 15, 2011 5:44 PM).
It turns out that it is a Weblogic specific issue when deploying anything using JSF and EJB. I found this post on the Oracle forums that explains how to get the #EJB injection working in JSF Managed Beans using Weblogic 11g:
EJB3.0 Injection into JSF Managed beans
UPDATE:
After spinning my wheels for too long, I have to give up trying to inject an EJB into a JSF ManagedBean on Weblogic 11g. Seems to work fine in Tomcat. Maybe the EJB3 and JSF implementation will be better in 12G...
To make it work you need to follow two steps:
Deploy jsf-2.0.war as LIBRARY, you can find it /ORACLE_HOME/wlserver_10.3/common/deployable-libraries
In your web project, add the reference to the jsf-2.0.war library in WEB-INF/weblogic.xml
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.1/weblogic-web-app.xsd">
<wls:weblogic-version>10.3.3</wls:weblogic-version>
<wls:context-root>your_context_app</wls:context-root>
<wls:library-ref>
<wls:library-name>jsf</wls:library-name>
<wls:specification-version>2.0</wls:specification-version>
<wls:implementation-version>1.0.0.0_2-0-2</wls:implementation-version>
<wls:exact-match>true</wls:exact-match>
</wls:library-ref>
</wls:weblogic-web-app>
I have successfully tested this in weblogic 10.3.3 and 10.3.5. If somehow this does not work, try to deploy the application as part of EAR file.
So here is the beat! There is a simple way to fix this.
Open up jsf-2.0.war under ...wlserver_10.3\common\deployable-libraries
Navigate to WEB-INF/lib and save wls.jsf.di.jar JAR somewhere
Place wls.jsf.di.jar JAR under lib folder of your WAR application.
Deploy
all should work now just by adding #EJB to property in your #ManagedBean.
There is an alternative for the #EJB annotation in order to get your local EJB bean accessible in your JSF ManagedBean web application. Considering that you have your EJB classes and your WAR packaged in the same EAR file, do the following:
configure your ejb-jar.xml to tell the weblogic expose the EJB beans to the external components;
<enterprise-beans>
<session>
<ejb-name>MyEJBBean</ejb-name>
<business-local>com.app.MyEJBBeanLocalInterface</business-local>
<ejb-class>com.app.MyEJBBeanLocalImpl</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBBeanLocal</ejb-ref-name>
<local>com.app.MyEJBBeanLocalInterface</local>
</ejb-local-ref>
</session>
<enterprise-beans>
Insert in the web.xml of your web application a reference to the EJB throught the ejb-link name. The ejb-ref-name is name visible for the JSF managed beans.
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBBeanLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>com.app.MyEJBBeanLocalInterface</local>
<ejb-link>MyEJBBean</ejb-link>
</ejb-local-ref>
In your JSF Managed Bean call the EJB Bean through JNDI lookup as the following:
try {
Context context = new InitialContext();
MyEJBBeanLocalInterface myEJBBean =
context.lookup("java:comp/env/ejb/MyEJBBeanLocal");
} catch (NamingException e) {
e.printStackTrace();
}
In my case I was using the Weblogic 10.3.6 (11g), JSF 2.0 and EJB 3.0 with JPA (Eclipselink)

JSF2.0 PostConstructApplicationEvent managed bean is null

We have JSF2.0 in Tomcat6.0 , need to initialize a ApplicationScope Bean while web server is started.
I tried using the PostConstructApplicationEvent processEvent method to initialize the Bean , but the managed bean from faces-config.xml is returning null.
Is there any other better way to instantiate the bean after startup?
Remove any faces-config.xml declarations related to the bean (they will otherwise override the JSF 2.0 annotations) and then annotate the bean with #ManagedBean(eager=true) as follows:
#ManagedBean(eager=true)
#ApplicationScoped
public class Bean {
// ...
}
This way the bean will always be instantiated on JSF webapp startup, without the need to view any page. You can then do the initialization job in the constructor and/or #PostConstruct of the bean.

Resources