Using Session Bean provided data on JSF welcome page - jsf

I use JSF managed beans calling EJB methods that are provide data from database. I want to use some data already on the welcome page of the application. What is the best solution for it?
EJBs are injected into JSF managed beans and it looks like the injection is done after executing the constructor. So I am not able to call EJB methods in the constructor.
The normal place for EJB call is in the JSF action methods but how to call such a method prior to loding the first page of the application?
A possible solution would be to call the EJB method conditionally in a getter that is used on the welcome page, for example:
public List getProductList(){
if (this.productList == null)
this.productList = myEJB.getProductList();
return this.productList;
}
Is there any better solution? For example, in some config file?

You can do it in a method which is annotated with #PostConstruct. This will be executed once after the bean is constructed and all JSF managed property and resource injection is done.
#PostConstruct
public void init() {
this.productList = myEJB.getProductList();
}

if you want to make a call from xhtml view
<f:view>
<f:metadata>
<f:viewAction action="${myController.init()}" onPostback="true"/>
</f:metadata>
</f:view>
and your controller
public class MyController{
public void init(){
this.productList = myEJB.getProductList();
...

Related

JSF - Invoke bean method at page load [duplicate]

Is there a way to execute a JSF managed bean action when a page is loaded?
If that's relevant, I'm currently using JSF 1.2.
JSF 1.0 / 1.1
Just put the desired logic in the constructor of the request scoped bean associated with the JSF page.
public Bean() {
// Do your stuff here.
}
JSF 1.2 / 2.x
Use #PostConstruct annotated method on a request or view scoped bean. It will be executed after construction and initialization/setting of all managed properties and injected dependencies.
#PostConstruct
public void init() {
// Do your stuff here.
}
This is strongly recommended over constructor in case you're using a bean management framework which uses proxies, such as CDI, because the constructor may not be called at the times you'd expect it.
JSF 2.0 / 2.1
Alternatively, use <f:event type="preRenderView"> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
JSF 2.2+
Alternatively, use <f:viewAction> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
Note that this can return a String navigation case if necessary. It will be interpreted as a redirect (so you do not need a ?faces-redirect=true here).
public String onload() {
// Do your stuff here.
// ...
return "some.xhtml";
}
See also:
How do I process GET query string URL parameters in backing bean on page load?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to invoke a JSF managed bean on a HTML DOM event using native JavaScript? - in case you're actually interested in executing a bean action method during HTML DOM load event, not during page load.
Another easy way is to use fire the method before the view is rendered. This is better than postConstruct because for sessionScope, postConstruct will fire only once every session. This will fire every time the page is loaded. This is ofcourse only for JSF 2.0 and not for JSF 1.2.
This is how to do it -
<html xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:event type="preRenderView" listener="#{myController.onPageLoad}"/>
</f:metadata>
</html>
And in the myController.java
public void onPageLoad(){
// Do something
}
EDIT - Though this is not a solution for the question on this page, I add this just for people using higher versions of JSF.
JSF 2.2 has a new feature which performs this task using viewAction.
<f:metadata>
<f:viewAction action="#{myController.onPageLoad}" />
</f:metadata>
#PostConstruct is run ONCE in first when Bean Created.
the solution is create a Unused property and Do your Action in Getter method of this property
and add this property to your .xhtml file like this :
<h:inputHidden value="#{loginBean.loginStatus}"/>
and in your bean code:
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
public String getLoginStatus() {
// Do your stuff here.
return loginStatus;
}
Calling bean action from a <p:remoteCommand> will be a good idea, keep attribute autoRun="true"
Example below
<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#{bean.action}" partialSubmit="true" update=":form" />

Running non get/set managed bean class function [duplicate]

Is there a way to execute a JSF managed bean action when a page is loaded?
If that's relevant, I'm currently using JSF 1.2.
JSF 1.0 / 1.1
Just put the desired logic in the constructor of the request scoped bean associated with the JSF page.
public Bean() {
// Do your stuff here.
}
JSF 1.2 / 2.x
Use #PostConstruct annotated method on a request or view scoped bean. It will be executed after construction and initialization/setting of all managed properties and injected dependencies.
#PostConstruct
public void init() {
// Do your stuff here.
}
This is strongly recommended over constructor in case you're using a bean management framework which uses proxies, such as CDI, because the constructor may not be called at the times you'd expect it.
JSF 2.0 / 2.1
Alternatively, use <f:event type="preRenderView"> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
JSF 2.2+
Alternatively, use <f:viewAction> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
Note that this can return a String navigation case if necessary. It will be interpreted as a redirect (so you do not need a ?faces-redirect=true here).
public String onload() {
// Do your stuff here.
// ...
return "some.xhtml";
}
See also:
How do I process GET query string URL parameters in backing bean on page load?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to invoke a JSF managed bean on a HTML DOM event using native JavaScript? - in case you're actually interested in executing a bean action method during HTML DOM load event, not during page load.
Another easy way is to use fire the method before the view is rendered. This is better than postConstruct because for sessionScope, postConstruct will fire only once every session. This will fire every time the page is loaded. This is ofcourse only for JSF 2.0 and not for JSF 1.2.
This is how to do it -
<html xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:event type="preRenderView" listener="#{myController.onPageLoad}"/>
</f:metadata>
</html>
And in the myController.java
public void onPageLoad(){
// Do something
}
EDIT - Though this is not a solution for the question on this page, I add this just for people using higher versions of JSF.
JSF 2.2 has a new feature which performs this task using viewAction.
<f:metadata>
<f:viewAction action="#{myController.onPageLoad}" />
</f:metadata>
#PostConstruct is run ONCE in first when Bean Created.
the solution is create a Unused property and Do your Action in Getter method of this property
and add this property to your .xhtml file like this :
<h:inputHidden value="#{loginBean.loginStatus}"/>
and in your bean code:
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
public String getLoginStatus() {
// Do your stuff here.
return loginStatus;
}
Calling bean action from a <p:remoteCommand> will be a good idea, keep attribute autoRun="true"
Example below
<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#{bean.action}" partialSubmit="true" update=":form" />

Getting application scoped bean in JSF 2.2 custom component

I am developing a new JSF 2.2 application.
I have an eagerly created, application scope managed bean that loads up some configuration data from an external file, at startup, and stores it as state.
I have a FacesComponent and FacesRenderer that I have working statically.
I would like to be able to get the configuration data stored in the managed bean into the FacesComponent. Is there a standard way to do this.
As far as I am aware, the managed bean cannot be injected into the component - is that correct?
I can try to get data into the custom component using attributes and el in the .xhtml file that uses the custom component e.g.
<my:customComponent data="#{managedBean.loadedData}"/>
but this seems like a really backwards way to do things and actually exposes internal implementation of the component to the component user.
Please let me know if there is another way, or if you need any more information.
Update: #BalsusC I have tried what you suggested
I have a loader that puts the loaded data into a holder object
#Named
#ApplicationScoped
public class Loader implements Serializable {
#Inject
private Holder holder
#PostConstruct
public void init() {
// Load data into the holder here
}
}
The holder is another application scoped bean
#Named
#ApplicationScope
public class Holder {...}
When loading the data the Holder instance is injected correctly into the Loader.
However when I they the following
#Named //Makes no difference if this is here or not
#FacesComponent(value="family", createTag=true, namespace="...namespace...", tagName="tag")
public class Component extends UIComponentBase {
#Inject
public class Holder holder;
#Override
public void encodeBegin(FacesContext context) {
holder.getData();
}
}
when the component comes to render, the holder is not injected and I get a null pointer exception. I have tried to do this with our without the #Named annotation with the same result.
Am I doing something wrong? Can you please advise.
Application scoped JSF managed beans are internally stored in the application map with the managed bean name as key.
So, the below inside any of UIComponent methods should do:
ManagedBean managedBean = (ManagedBean) getFacesContext().getExternalContext()
.getApplicationMap().get("managedBean");
// ...
This only makes the component tight coupled to the managed bean. I.e. the component can't exist without the managed bean. This should be clearly documented if the component is intented to be reusable in other webapps. Another option is to tie the managed bean exclusively to the component (perhaps in form of a composite component) and use another application scoped bean for "unrelated" application data.

How to instantiate a backing bean on page load

For a project we are migrating some java applications to WebSphere 8.5. In the process we are trying to get rid of some legacy frameworks. One of them is shale (apache attic). The only component from shale that is used is the view controller to instantiate a request scoped jsf managed beans for every page. Every bean has an init method that is called on page load. I'd like to use #PostConstruct on this method. The only problem I have that the bean gets instantiated when a method on the bean is called. Unfortunately the bean is not always called and the init method does populate data on a session scoped bean. There is a naming convention that links pages and beans so we could use a listener to instantiate the bean based on the request. Another solution might be changing the scope to viewscope (probably to much a hassle on websphere 8.5).
I was wondering if there is something I can do to make the PostConstruct work? And are there other options I'm missing?
edit:
I have a PhaseListener in place that performs the basic functionality. It matches the requested page to the corresponding bean (by naming convention). The following is used to instantiate the bean but it looks a bit ugly.
expressionFactory.createValueExpression(elContext, "#{" + managedBeanName + "}", Object.class)
Is there a more elegant way to do this?
Perhaps you could try using <f:event/> ?
In your view, you could add this to the page.
<f:event type="postAddToView" listener="#{backingBean.myInitMethod()"/>
https://stackoverflow.com/a/14004230/4706826
Gives you info on when the events get executed.
Put a #PostConstruct annotated method in the backing bean. This annotation tells the bean to execute the annotated method every time its constructor is being called.
Example:
#ManagedBean
#ViewScoped
public class MyManagedBean{
#PostConstruct
public void initView() throws Exception{
...initialize page values, execute database queries, etc.
}

How does EL #{bean.id} call managed bean method bean.getId()

I do not really understand how getter and setter work althougth it is a basic concept. I have the following code, how is the attribute id sent to Managed Bean? Is it captured by getter method?
My facelet
<p:inputText id="id" value="#{bean.id}">
My managed bean
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
The call of getter and setter methods by #{} expressions is not part of JSF but Expression Language (most known as EL). JSF takes advantage of EL to bind the data of the HTML components to the fields of a bean through proper getters and setters. This is:
If the bean exists, Expression Language will execute the proper getter of the registered bean in the proper scope.
If client performs a form submission or an ajax request, then the components that are sent to the server (usually all the components in the <h:form>, in case of ajax requests you can state which components to send to the server) will contain a new value, and this value will be set to the field with the proper setter method.
For example, you have a SayHelloBean which belongs to request scope:
#RequestScoped
#ManagedBean
public class LoginBean {
private String name;
//proper getter
public String getName() {
return this.name;
}
//proper setter
public void setName(String name) {
this.name = name;
}
}
And these 2 facelets pages (since it's an example I avoid declaring <html>, <h:head>, <h:body> and other elements, just focusing on the relevant code)
Page1.xhtml:
<h:form>
Please tell me your name
<h:inputText value="#{loginBean.name}" />
<h:commandButton action="page2" />
</h:form>
Page2.xhtml:
Hello #{loginBean.name}
This is what happens behind the scenes:
When Page1.xhtml is loaded, a new instance of LoginBean, which we may call loginBean, will be created by JSF and registered into JSP request scope. Since the value of <h:inputText /> is bound to LoginBean#name (which is read as the field name of LoginBean class), then EL will display the value of loginBean#name (which is read as the field name of instance loginBean), and since that is not initialized, EL will display null, as an empty string.
When you submit the form of Page1.xhtml, since LoginBean is #RequestScoped then JSF will create a new instance of LoginBean, which we may call it loginBean2 (adding 2 in the end because this instance is totally different from the loginBean previously created) and will register it in JSP request scope. Since the value of <h:inputText /> is bound to LoginBean#name, JSF will validate and set the data by calling the proper setter. This will make loginBean2#name have the value of the <input type="text"> that was rendered by <h:inputText/>.
At last, JSF will make sure to navigate to Page2.xhtml through forward, where when processing it, it will find #{loginBean.name} and EL will check for the value of loginBean2#name and replace it.
The steps explained here are a very small explanation (and with lot of elements not explained) of the JSF lifecycle and how JSF uses getters and setters.
More info:
How to pass parameter to jsp:include via c:set? What are the scopes of the variables in JSP?
How to choose the right bean scope?
The Lifecycle of a JavaServer Faces Application
Differences between Forward and Redirect
Additional note: since you're learning JSF, avoid putting any business logic code in getters/setters. This is greatly explained here: Why JSF calls getters multiple times
Whenever you use something like
#{someBean.someField}
the EL looks for a someBean.getSomeField() or someBean.setSomeField(...) method, depending on whether you're reading that field or writing in it (which can easily be inferred from the context). JSF never accesses a field directly (i.e without making use of its getter or setter). Try deleting the getter and setter of a given field and you'll see it won't work.

Resources