Does JSF Managed Bean scope impacts visibility & access between EAR, WAR and JAR - jsf

I have EAR with in Which WAR & few JARS. Eventually few more JARS under my WAR too.
I have packaged a set of DATA OBJECTs inside a EAR as JAR, out which one of its Managed Bean is under 'SessionScope' and with its property -> 'eager = true'. Say 'A.Java'
Now, From My WAR I have a ManagedBean, say 'B.java', with 'RequestScope' trying to get an instance of A.java, Which is returned as NULL. From the Logs, When traced got the below exception:
The managed-bean with name 'B' must be application scoped to support eager=true.
Is there a hierarchy of Managed Bean Scope, that we have to ensure while archiving and deploying as EAR???

Eager Application-Scoped Beans
Managed beans are lazily instantiated. That is, that they are instantiated when a request is made from the application.
To force an application-scoped bean to be instantiated and placed in the application scope as soon as the application is started and before any request is made, the eager attribute of the managed bean should be set to true as shown in the following example:
#ManagedBean(eager=true)
#ApplicationScoped
The eager property means that the container creates the instance at application startup and not on demand. It can put this instance just into the application scope. (There are no other scopes at this time). So the eagerly created managed beans must be ApplicationScoped.

Related

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 use HTTP Session Scope in portlets ?

In my application there are 5 portlets accessing same bean class which is in session scope. My problem is, whenever I open a portlet, managed bean initializes. Managed bean should be initialize once in a session. In my case bean initializing 5 times. Can anyone tell me what is the root cause of that problem?
Here is my bean :
#ManagedBean(name="userManagementBean")
#SessionScoped
public class UserManagementBean {
public UserManagementBean() {
System.out.println("In getter setter bean");
sName=userManagementHelper.findScreenName();
directReport=new DualListModel<String>();
addUserToGroupDual=new DualListModel<String>();
addUserToGroupDual.getSource().clear();
addUserToGroupDual.getTarget().clear();
............
When you annotate your beans with #SessionScoped in Portlet application it is mapped to something as "Portlet Instance Session". This means that this bean will live in session of that portlet, and each portlet has its own session. There is something called "Global Session" which is session shared across all portlets, but as far as I know there is not such annotation in JSF.
JSR286 has user session based scope but it would depend on your portal server if it has the implementation for this as a Custom Scope for JSF.
I know for sure that Websphere portal 8.x supports this.
In Websphere portal 8.x you can specify your managed bean like,
#ManagedBean(name="userManagementBean")
#CustomScoped("#{portletApplicationSessionScope}")
public class UserManagementBean {
...
}
Have a look into your portal server documentation to see if it supports that.
You can use Apache JSF portlet bridge as you have updated that you are using liferay ,
It will expose Application Session Scope as EL,
Add it to application scope in portlet A
PortletSession session = request.getPortletSession();
session.setAttribute("name",name.getValue().toString(),PortletSession.APPLICATION_SCOPE);
and use in portlet B
PortletSession session = request.getPortletSession();
String value = session.getAttribute("name", PortletSession.APPLICATION_SCOPE).toString();
Your xhtml ,
<h:inputText id="itName"
required="true"
value="#{httpSessionScope.name}"/>

JSF / EJB3 avoiding lazy initialization exceptions in the view layer

I have the following JSF/PrimeFaces EJB architecture:
[JSF/PrimeFaces xhtml view] --> [#ManagedBean JSF bean] --> [#Stateless EJB3 bean] --JPA--> [DB]
That is, the JSF views display entities and collections they access on their backing beans (#ManagedBean) and these collections and entities are in turn fetched by calling stateless EJB3 "facade" beans that have the EntityManager injected and access the database using JPA backed by Hibernate. The stateless EJB3 beans also provide some services but for the most part their role is to provide the Entity objects (JPA-annotated) from the database, as requested by the xhtml views that need to display them.
Now here's the thing: if my understanding is correct, the moment the Entity beans are returned by the stateless EJB3 beans, they become detached as each EJB3 bean method demarcates a transaction. It is then often the case that as the xhtml views and the JSF Managed beans navigate the graphs of the Entity objects so fetched (One-To-Many collections and such), I often get Lazy Initialization exceptions like the following:
javax.el.ELException: ... org.hibernate.LazyInitializationException: failed
to lazily initialize a collection of role: ..., no session or session was closed
The only thing that works is changing collections to be EAGER -ly loaded but that's not a pragmatic solution. What are some good patterns to use when detached JPA entity find their way to the view layer in order to avoid once and for all the lazy initialization exceptions rather than having to treat each case in an ad-hoc manner?
There are two ways of handling lazy associations. The first way is to initialize the entity using:
Hibernate.initialize(proxy)
or set the fetch type to EAGER which will fetch the entire entity when you load it.
The second and the more proper way (in my opinion) is to keep the entity manager as long as you keep the entities. This could be done either using a #Stateful session like this:
#Stateful
public class UserService {
#PersistenceContext(type=EXTENDED)
private EntityManager entityManager;
...... the business method
}
and keep a reference to the ejb as long as you keep the entity. More info about extended persistence context could be found here.
Other way to keep the entity manager is to use CDI modules like seam-persistence or CODI that offer a functionality to create and keep an EntityManager to conversation scope.

Update faces-config.xml in memory at runtime

When a JSF/XPages application starts it reads the faces-config.xml for managed beans, validators etc. Can I manipulate the loaded configuration at runtime? e.g. dynamically add a validator to ensure my custom code will run.
I'm not trying to change the xml file at runtime, but the memory representation after it gets loaded.
XPages uses a JSF 1.x runtime,so JSF 2.0 constructs might not work
Yes, you can add a lot of JSF artifacts which are normally configured in faces-config.xml by among others the Application class as well.
Application application = FacesContext.getCurrentInstance().getApplication();
application.addValidator("fooValidator", "com.example.FooValidator");
// ...
You could do the job in an eagerly initialized application scoped managed bean.
#ManagedBean(eager=true)
#ApplicationScoped
public class Config {
#PostConstruct
public void init() {
// ...
}
}

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)

Resources