I lost my data of sessionScope - jsf

I am having a problem with JSF 2.2, I have this struct:
Problem: I can not set variables (by sessionScope - MainBean) since catalog.xhtml (by requestScope/ViewScope - CatalogBean).
LoginBean: SessionScope
#ManagedBean(name="loginBean")
#SessionScoped
public class LoginBean {
private Session userLog;
MainBean: SessionScope
#ManagedBean
#SessionScoped
public class MainBean {
#ManagedProperty(value="#{loginBean}")
private LoginBean userLogin;
CatalogBean: ViewScope/RequestScope
#ManagedBean
#ViewScoped
public class CatalogBean {
#ManagedProperty(value="#{mainBean}")
private MainBean userManagerCatalog;
ItemBean: ViewScope/RequestScope
#ManagedBean
#ViewScoped
public class ItemBean {
#ManagedProperty(value="#{mainBean}")
private MainBean userManagerItem;
The problem is when I enter in item.xhtml (ItemBean) , (since catalog.xhtml) I am saving a variable in MainBean (SessionScope), with:
<p:commandLink action="item.xhtml?faces-redirect=true" actionListener="#{mainBean.setSelectedItem(it)}">
<p:graphicImage library="resources" name="images/folderNormal.png" style="width: 100; height: 100"/>
<f:setPropertyActionListener value="#{it}" target="#{mainBean.selectedItem}" />
</p:commandLink>
Data of Interest
*I had been to using two diferent forms (actionListener and setPropertyActionListener)
**I have to enter catalog to enter the item
*** I am bugging, this makes the change but the next, I see that the program lost this data
**** I had used in Catalog the property SessionScope (fuction well) but I can not change of catalog because the variable does not change its value.
Any help is welcome, thanks in advance

Related

After migration from JSF #ManagedBean to CDI #Named, constructor called multiple times and submitted input values always null

Edit: The comment section solved my problem! The problem was that I was using incorrect imports for the Scopes.
I have a simple JSF application (login, pull data from database, allow user to edit data). It works well, I want to update the code to use CDI (Weld), but I am having trouble.
I am following / looking at: http://docs.jboss.org/weld/reference/latest/en-US/html/example.html
Original stuff without Weld:
login.xhtml
<h:form id="inputForm">
<h:panelGrid columns="2" cellpadding="5" cellspacing="1">
<h:outputText id="nameDesc" value="Name"></h:outputText>
<h:inputText id="nameInput" value="#{login.loginName}" binding="#{name}"></h:inputText>
<h:outputText id="passwordDesc" value="Password"></h:outputText>
<h:inputSecret id="passwordInput" value="#{login.password}" binding="#{password}"></h:inputSecret>
</h:panelGrid>
<h:commandButton value="Login" action="#{login.login(name.value, password.value)}"/>
</h:form>
LoginBean.java:
#ManagedBean(name="login")
#SessionScoped
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
#ManagedProperty(value="#{db}")
private DatabaseBean db;
private String password;
private String loginName;
// other stuff and functions
public String getLoginName () {
return loginName;
}
public void setLoginName (String name) {
this.loginName = name;
}
public String getPassword () {
return password;
}
public void setPassword (final String password) {
this.password = password;
}
public void setDb(DatabaseBean db) {
this.db = db;
}
DatabaseBean.java:
#ManagedBean(name="db", eager=true)
#ApplicationScoped
public class DatabaseBean implements Serializable {
#PostConstruct
public void init() {
//... connect to database etc
}
}
---------What I tried to get it running with Weld (only changes from above to make it a bit shorter): --------
LoginBean.java, changed to #Named from #ManagedBean, added #Inject for DatabaseBean
#Named("login")
#SessionScoped
public class LoginBean implements Serializable {
// stuff
private #Inject DatabaseBean db;
}
DatabaseBean.java, changed to #Named from #ManagedBean:
#Named("db")
#ApplicationScoped
public class DatabaseBean implements Serializable {
}
LoginBean has a function:
public String login(String name, String password) {
System.out.println("login called"+name);
// other stuff
}
With my second implementation (the one where I try to use Weld), the print is called once: "login called", and the username is empty (I checked this with name.IsEmpty()).
I have also tried injecting it by constructor:
loginBean.java
#Inject
public LoginBean(DatabaseBean db) {
System.out.println("constructor");
this.db = db;
}
When I do this the I get lots of "constructor" prints, so it is called several times, but I don't see why - I guess this is the problem though, only one instance of LoginBean gets the input (username and password) and then lots of new ones are created for some reason. Why is that?
I use Eclipse and Tomcat8 to run it.
Thank you for reading!
managed bean constructor called multiple times
CDI may call constructor more often than expected while generating/creating enhanced subclasses/proxies. See also Field.get(obj) returns all nulls on injected CDI managed beans, while manually invoking getters return correct values. Just do not log constructor invocation, it would only confuse yourself. #PostConstruct is the only interesting method to hook on.
the print is called once: "login called", and the username is empty (I checked this with name.IsEmpty()).
As to the concrete problem of form input values being null when the action method is invoked, and thus the #SessionScoped CDI managed bean seemingly being recreated on every access, this matches the behavior of a #Dependent scoped bean. This is the default scope when no valid CDI managed bean scope can be found. See also What is the default Managed Bean Scope in a JSF 2 application?
This in turn suggests you imported #SessionScoped from the wrong package. Make sure it's from the javax.enterprise.context package and not from e.g. javax.faces.bean. JSF managed bean scopes are not recognizable as valid CDI managed bean scopes.
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
#Named("login")
#SessionScoped
public class LoginBean implements Serializable {
// ...
}

Named Bean not injected into another named bean

I am trying to inject a named bean in another one.
When I try to access properties of the injected bean , it returns null which means that the injection fails.
Here is the first Bean:
#Named
#SessionScoped
public class FirstMBean {
String caracter;
..........
public String goToNext(){
String caracter=FacesContext.getCurrentInstance().getExternalContext().
getRequestParame‌​terMap().get("caracter"); this.caracter=caracter;
System.out.println("the selected caracteris"+ caracter);
return "/pages/next?faces-redirect=true"; }
}
The second named bean:
#Named
#SessionScoped
public class SecondMBean {
#Inject
FirstMBean firstMBean ;
String injectedCaracter ;
#PostConstruct
public void init() {
this.injectedCaracter = this.firstMBean.getCaracter();
System.out.println("injectedCaracter ----" + this.injectedCaracter);
}
In my .xhtml page :
<p:commandButton value="see caracter" action="#{firstMBean.goToNext}">
<f:param name="caracter" value="#{caracter}" />
</p:commandButton>
Please note that I am using tomcat server to which I added WELD to support CDI AND when I put the scope to ApplicationScoped, everything works fine.

Pass a param from ManagedBean to jsf page

I am working with JSF 2.2 and Tomcat 8 and I am just starting to play with them.
I have a command button in a jsf page.
<h:commandButton id="newObject" value="New Object" action="#{someObject.someAction}">
<f:param name="object_id" value="#{someObject.object_id}" />
</h:commandButton>
The ManagedBean is similar to this:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
#ManagedBean
public class SomeObject implements Serializable{
private static final long serialVersionUID = 1L;
private int object_id;
public int getObject_id() {
return object_id;
}
public void setObject_id(int object_id) {
this.object_id = object_id;
}
public String someAction() {
setObject_id(sqlInsert());
if(getObject_id() != 0) {
System.out.println(getObject_id());
return "new_page";
}
}
}
The sqlInsert method is working fine. I use it to insert a new row in some sql table and get the auto generated key, which is an int. If the insert did not happen it would return 0.
I can navigate to the new_page, but the param object_id is 0. I added println to show the object_id and it is the actual key.
What am I doing wrong?
Since you are using the only #ManagedBean annotation on your Managed Bean and not specifying any Scope of you bean explicitly, your Bean will act as if its a #RequestScoped bean.[See link]
So every time you click your New Object button, the Bean is re initialized and you will loose the state(variable values).
Think and decide which scope you want to use [See link]. For your requirements #ViewScoped might do the job for you.

How to share data between two #ViewScoped beans?

I am trying to pass id (long) from one.xhtml to another .xhtml.
Both the backing beans are #ViewScoped and I am trying to share long id between them.
I am getting error with <f:viewParam/>
com.sun.faces.mgbean.ManagedBeanCreationException: Unable to create
managed bean saleOrder. The following problems were found:
- The scope of the object referenced by expression #{param.foo}, request, is shorter than the referring managed beans (saleOrder) scope of view.
I am have following code.
#ManagedBean
public class InvoiceView{
private long number;
// setter getter.
}
#ManagedBean
#ViewScoped
public SearchInvoice{
private List<InvoiceView> views;
private InvoiceView selectedView; // this is coming from <p:dataTable>
}
#ManagedBean
#ViewScoped
public class SaleOrder {
#ManagedProperty("#{param.foo}")
private String number;
#PostConstruct
public void init(){
//sysout number;
}
}
I have following code in searchInvoice.xhtml file.
<!-- I have not desclared <f:metadata/> -->
<h:commandButton value="Place Sale Order"
action="#{searchInvoice.forwardToSaleOrder}" <!-- this return saleOrder.xhtml string -->
rendered="#{not empty searchInvoice.views}">
<f:viewParam name="foo" value="#{searchInvoice.selectedView.number}" />
</h:commandButton>
You can use <f:viewParam> (JSF 2) in saleOrder.xhtml, which works with view scoped beans.
Check out this article.

Button not submit PrimeFaces 3.5

i'm using jsf + primefaces 3.5. And my button isn't calling one method in my managed bean.
I have this xhtml:
<h:form>
<p:inputText id="name" value="#{userMB.userSelected.name}" />
<p:commandButton id="btnSave" value="Salvar" actionListener="#{userMB.save}"/>
</h:form>
And my managed bean is:
#ManagedBean
#SessionScoped
public class UsuarioMB implements Serializable{
User userSelected;
public void save(){
System.out.println(userSelected.getName());
//call my daos and persist in database
}
}
The most curious is that if i remove the , the method is called!
If i put a atribute in p:commandButton "imediate = true ", the method is called, BUT, the information (userSelected.name) is null !
Thanks very much :)
It failed because it threw a NullPointerException because you never initialized userSelected.
Add this to your bean:
#PostConstruct
public void init() {
userSelected = new User();
}
If you have paid attention to the server logs, you should have seen it. As to the complete absence of feedback about the exception in the webbrowser, whereas in normal synchronous (non-ajax) you would have seen a HTTP 500 error page, it's because you're sending an ajax request without apparently an ExceptionHandler configured.
That it works when you set immediate="true" on the button is simply because it will then bypass the processing of all input components which do not have immediate="true" set.
See also:
What is the correct way to deal with JSF 2.0 exceptions for AJAXified components?
You have not given a name to the managedbean UsuarioMB. As suche it will be named usuarioMB.
#ManagedBean – marks this bean to be a managed bean with the name
specified in name attribute. If the name attribute in #ManagedBean is
not specified, then the managed bean name will default to class name
portion of the fully qualified class name.
read more about it in this blog: http://mkblog.exadel.com/2009/08/learning-jsf2-managed-beans/
Secondly, if your code above is complete, you are lacking public getter and setter for userSelected.
Thirdly you are missing the ActionEvent as you have declared a parameterless actionlistener, see Differences between action and actionListener
In order to get you code working you will need to change your xhtml to
<h:form>
<p:inputText id="name" value="#{usuarioMB.userSelected.name}" />
<p:commandButton id="btnSave" value="Salvar" actionListener="#{usuarioMB.save}"/>
</h:form>
And your managed bean as follows
import javax.faces.event.ActionEvent;
// ...
#ManagedBean
#SessionScoped
public class UsuarioMB implements Serializable{
private User userSelected;
public void save(ActionEvent event){
System.out.println(userSelected.getName());
}
public User getUserSelected() {
return userSelected;
}
public void setUserSelected(User userSelected) {
this.userSelected = userSelected;
}
}

Resources