#ManagedProperty - Inject one request scoped bean into another request scoped bean - jsf

I have this SearchBean:
#ManagedBean(name = "searchBean")
#RequestScoped
public class SearchBean implements Serializable
{
private String input = null;
// getter methods
public String getInput() {
return input;
}
// setter method
public void setInput(String input) {
this.input = input;
}
public String Submit() {
return null;
}
}
Can I inject it into another bean using #ManagedProperty. For example:
#ManagedBean(name = "bookBean")
#RequestScoped
public class BookBean implements Serializable
{
#ManagedProperty(value = "#{searchBean}")
private SearchBean searchBean;
#PostConstruct
public void init()
{
System.out.println("Value: " + searchBean.getInput());
}
public SearchBean getSearchBean() {
return searchBean;
}
public void setSearchBean(SearchBean searchBean) {
this.searchBean = searchBean;
}
}
And the Facelet (search.xhtml):
<h:form id="formSearch">
<h:commandButton value="Search" action="#{searchBean.Submit}" />
</h:form>
UPDATE: I have search.xhtml inserted into book.xhtml via a ui:insert component as follow:
<h:form id="formBooks">
<ui:insert name="search">
<ui:include src="/templates/common/search.xhtml"/>
</ui:insert>
</h:form>
The searchBean.getInput() method above should return a value as a result of a form's submission. Is the above method of injection possible?

I assume that SearchBean.input will be bound to an input field:
public class SearchBean implements Serializable {
private String input = null;
Something like this:
<h:inputText value="#{searchBean.input}" />
If so, then this will be null:
#PostConstruct
public void init()
{
System.out.println("Value: " + searchBean.getInput());
}
But, assuming a value has been set, it will not be null when this method is invoked:
public String Submit() {
return null;
}
Image from Richard Hightower's JSF for nonbelievers: The JSF application lifecycle.
The reason is due to how the JSF lifecycle works:
When #{searchBean...} is first resolved and found not to exist:
The bean is instantiated
Any dependency injections are performed (there aren't any in this case)
#PostConstruct method is invoked
The bean is placed into scope
Assuming the Apply Request Values and Validations phases succeed, SearchBean.setInput(String) is invoked in the Update Model Values phase
SearchBean.Submit() is invoked in the Invoke Application phase
This process is defined in the JSF specification.
Now, if SearchBean.input were injected directly from the parameter map, it would not be null during #PostConstruct:
#ManagedProperty(value = "#{param.someParamName}")
private String input;
However, there aren't any real advantages to this - you're skipping any input validation and you can't use SearchBean.input as a field binding because it will be overwritten in the Update Model Values phase.
The SearchBean.Submit() method is where your application logic for performing the search should go.

Related

Passing value between JSF Forms. I can't get it to work

I read the other posts about this subject but I still can't get it to work
This are my beans:
Bean1:
#ManagedBean()
#SessionScoped
public class Bean1 implements Serializable {
//Here are some important Properties
public String buttonPressed() {
return "bean2.xhtml";
}
}
<h:form>
<p:commandButton action="#{Bean1.buttonPressed}" value="Do Work"/>
</h:form>
Bean2:
#ManagedBean()
#SessionScoped
public class Bean2 implements Serializable {
#ManagedProperty(value = "#{Bean1}")
private Bean1 b1;
//getter/setter is here
public String doWorkOnSubmit() {
//Access important Properties from bean1
b1.getFoo()
}
}
Now I have two Problems
1.) How to call "doWorkOnSubmit" if the button in Bean1 is pressed? I can't use the constructor because it's SessionScoped and I don't know how to call doWorkOnSubmit un submit
2.)The managed property "b1" is sometimes null
Since on clicking of Do Work button you are calling Bean1.buttonPressed() action method you can call Bean2s doWorkOnSubmit() by injecting Bean2 in Bean1.
Here is your code altered:
#ManagedBean()
#SessionScoped
public class Bean1 implements Serializable {
//Here are some important Properties
/*
* Inject Bean2 here. since both beans are session scoped,
* there ain't gonna be any problem in injection.
*/
#ManagedProperty(value = "#{Bean2}")
private Bean2 b2;
//GETTER SETTER for b2
public String buttonPressed() {
//Here you will be invoking injected managed beans method.
b2.doWorkOnSubmit();
return "bean2.xhtml";
}
}

a method in a view Scoped bean in jsf is called 2 times just with one request

in our project, by click a primeFaces command button, a method in a jsf viewScoped bean is called. in this method, a method in a ejb stateless bean is called which in a loop(for loop) execute a query in database. during of run this method in ejb bean, another thread calls the method in the viewScoped bean without any new request and this 2 threads run concurrently. and at end, no results return to client.
commandButton in xhtml form:
<p:commandButton id="btnTestExecute"
value="run"
actionListener="#{drawingEditBean.testExecute()}"
process="#all"
update=":mainForm"
ajax="true"
icon="fa fa-trophy"
oncomplete="blinkNextButton()"/>
jsf bean:
public abstract class DrawingBean implements BaseBean {
private List<DrawingWinnerDto> testResult;
#EJB
private DrawingService drawingService;
#PostConstruct
#Override
public void init() {....}
public void testExecute() throws Exception {
LOG.debug("testExecute started");
testResult = drawingService.execute(drawingHeaderDto.getId());
LOG.debug("testExecute finished");
}
}
#Named
#ViewScoped
public class DrawingEditBean extends DrawingBean {
public static String PAGE_TITLE = "DrawingEdit";
public String getPageTitle() {
return PAGE_TITLE;
}
}
ejb bean:
#Stateless
public class DrawingService {
public List<DrawingWinnerDto> execute(Long drawingId) throws Exception {
Drawing drawingEntity = entityManager.find(Drawing.class, drawingId);
List<DrawingWinnerDto> retValue = new ArrayList<>();
Query queryAlgorithm2Core = entityManager.createNamedQuery("DrawingService.Drawing_Algorithm2_Core");
queryAlgorithm2Core.setParameter("drawing_id", drawingEntity.getId());
queryAlgorithm2Core.setParameter("winner_list", new LargeList("Number_List", winnerCandidates));
for (Reward reward : drawingEntity.getRewards()) {
for (int i = 0; i < reward.getQuantity(); i++) {
Object[] result = (Object[]) queryAlgorithm2Core.getSingleResult();
.....
}
}
return retValue;
}
}
by clicking the command button, testExecute() method is called. and inside it, execute() method is called. during run this method(execute() method), another thread calls the testExecute() method. at end of no thread runs, results show in browser.
please help me!

For exact same JSF EL expression, getter is being called for ouputText but not for inputText. Why?

This is my JSF pages
<h:form>
First Name: <h:inputText value="#{userBean.first}" valueChangeListener="#{userBean.updateLastName}" onblur="submit()"/><br/>
Last Name: <h:inputText value="#{userBean.last}"/><br/>
Last Name: <h:outputText value="#{userBean.last}"/><br/> </h:form>
Following is the managed bean code.
#Named
#RequestScoped
public class UserBean {
private Map<String, String> names;
private String first, last;
public UserBean() {
names = new HashMap<>();
names.put("first1", "last1");
names.put("first2", "last2");
}
public String getFirst() {return first;}
public void setFirst(String first) {this.first = first;}
public String getLast() {return last;}
public void setLast(String last) {this.last = last;}
public void updateLastName(ValueChangeEvent e){
last = names.get(e.getNewValue().toString());
FacesContext.getCurrentInstance().renderResponse();
}
}
Now, when I type "first1" on the FirstName field and tab out, I see "last1" on the outputText field but inputText field remains empty.
I did the debugging and found getter is being called only once, so I wonder why getter is not being called for the inputText? Considering EL Expression is exactly same and based on my knowledge getter should be called during Render Response phase???

Show how many Users logged in with JSF

i trie to run this code
#ManagedBean
#ApplicationScoped
public class Controller implements Serializable {
private static final long serialVersionUID = 1L;
private Benutzer benutzer;
private List<Erfasst> bisherErfasst = new ArrayList<Erfasst>();
private EntityManagerFactory emf = Persistence
.createEntityManagerFactory("CP Kontrolle");
private static Controller instance = new Controller();
public Benutzer getBenutzer() {
return benutzer;
}
public boolean anmelden(String email, int kdnr) {
EntityManager em = emf.createEntityManager();
Query query = em
.createQuery("SELECT b FROM Benutzer b WHERE b.email = :email AND b.kdnr = :kdnr");
query.setParameter("email", email);
query.setParameter("kdnr", kdnr);
List<Benutzer> liste = query.getResultList();
em.close();
if (liste.size() == 1) {
benutzer = liste.get(0);
AngemeldeteBenutzer.getAb().hinzufuegen(benutzer);
return true;
} else {
return false;
}
}
public static Controller getInstance() {
return instance;
}
[....]
}
}
The above code is my ControllerBean. From the Login-Form, user data will be checked in the "anmelden" Class and return true or false if it was successfully.If successfully, the user will be store into a list, as you can see.
#ManagedBean
#ApplicationScoped
public class AngemeldeteBenutzer implements Serializable {
private static final long serialVersionUID = 1L;
private List<Benutzer> online = new LinkedList<Benutzer>();
private static AngemeldeteBenutzer ab = new AngemeldeteBenutzer();
public static AngemeldeteBenutzer getAb() {
return ab;
}
public List<Benutzer> getOnline() {
return online;
}
public void hinzufuegen(Benutzer benutzer) {
online.add(benutzer);
}
}
This is my other Bean, which store the successfully logged user into a list.
Now i want to list all user into my table, but my table is still empty. No errors!
<h:panelGrid columns="2" id="onlinePanel" >
<h:dataTable value="#{angemeldeteBenutzer.online}" var="on">
<h:column>
<f:facet name="header">Email</f:facet>
<h:outputText value="#{on.email}"></h:outputText>
</h:column>
</h:dataTable>
</h:panelGrid>
The mistake is here:
private static Controller instance = new Controller();
public static Controller getInstance() {
return instance;
}
private static AngemeldeteBenutzer ab = new AngemeldeteBenutzer();
public static AngemeldeteBenutzer getAb() {
return ab;
}
You seem to have missed the point of a bean management framework with dependency injection support. You seem to be expecting that #{angemeldeteBenutzer} in the JSF page is referring exactly the same instance as you manually created there with new operator and are filling with users.
This is Wrong! You have there two instances of the class, one automatically created by JSF and available via #{angemeldeteBenutzer} and another one manually created by yourself and available via that getAb() method only.
Get rid of all those static fields and methods. They don't belong there. Instead, use #ManagedProperty to let JSF inject managed beans in each other. Add this code to the Controller class.
#ManagedProperty("#{angemeldeteBenutzer}")
private AngemeldeteBenutzer ab;
public AngemeldeteBenutzer getAb() {
return ab;
}
public void setAb(AngemeldeteBenutzer ab) {
this.ab = ab;
}
And replace in the same Controller class this line
AngemeldeteBenutzer.getAb().hinzufuegen(benutzer);
by
ab.hinzufuegen(benutzer);
Note: if you're already on Java EE 7, consider using CDI #Named instead of JSF #ManagedBean. When injecting via #Inject instead of #ManagedProperty, you don't need those ugly getter/setter anymore.
#Named
#ApplicationScoped
public class AngemeldeteBenutzer {
}
#Named
#ApplicationScoped
public class Controller {
#Inject
private AngemeldeteBenutzer ab;
}
Unrelated to the concrete problem, the Controller doesn't seem to be a legit application scoped bean. It looks too much like a view scoped bean due that view-specific variables and business logic. Make sure you understand the scopes: How to choose the right bean scope?

How to get inputTextArea value into another bean?

I want to get the value with the getter method, but it doesn't work. I use SessionScoped into my two managed-beans.
<h:outputLabel for="commentInput" value="Comment:" />
<p:inputTextarea id="commentInput" value="#{dashboardBean.currentComment}" rows="6" cols="25" label="commentInput" required="true"/>
#ManagedBean
#SessionScoped
public class DashboardBean implements Serializable
{
private String _currentComment = null;
public String getCurrentComment() {
return this._currentComment;
}
public void setCurrentComment(String _currentComment) {
this._currentComment = _currentComment;
}
}
If i call getter in this class, it's works.
But in the other class:
#ManagedBean
#SessionScoped
public class PanelListener extends AjaxBehaviorListenerImpl
{
private DashboardBean _dashDashboardBean = null;
public void editMemo(ActionEvent actionEvent)
{
System.out.println("Statements ==== [ " + _dashDashboardBean.getCurrentComment() + " ]");
}
}
I have an NullPointerException.
You need to use #ManagedProperty annotation to inject one bean into another.
#ManagedProperty("#{dashboardBean}")
private DashboardBean bean;
public DashboardBean getBean(){
return this.bean;
}
public void setBean(DashboardBean bean){
this.bean = bean;
}
Make sure the scope of the ManagedProperty is greater than or equal to the scope of bean in which you are injecting.
so here, DashBoardBean should have scope greater than or equal to PanelListener
Please note that JSF needs public getters and setters to access the fields
You have to use #ManagedProperty annotation. So try this in PanelListener, note that you need a setter to perform the bean injection. You can also only inject beana with greater or same scope to the bean with lower scopes (so for example you can inject SessionScoped to the RequestScoped but not the other way around).
#ManagedProperty("#{dashboardBean}")
private DashboardBean bean;
private void setDashboardBean(DashboardBean bean) {
this.bean = bean;
}

Resources