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?
Related
Still learning JSF and Java and having trouble understanding how to access a session bean property.
I have a LoggedUser session bean which sets the user that is logged in(using the login method).
#ManagedBean(name="loggedUser")
#Stateless
#LocalBean
#SessionScoped
public class LoggedUser {
#EJB
UserEJB userEJB;
#PersistenceContext
private EntityManager em;
private UserEntity loggedUser;
private String loginUserName;
private String loginPassword;
public LoggedUser() {}
public UserEntity getLoggedUser() {
return loggedUser;
}
public void setLoggedUser(UserEntity loggedUser) {
this.loggedUser = loggedUser;
}
public String authenticate() {
if (loggedUser == null) {
return "login.xhtml";
} else {
return "";
}
}
public String login() {
if (userEJB.validateLogin(loginUserName, loginPassword)) {
setLoggedUser(userEJB.fetchUser(loginUserName));
return "index.xhtml";
}
return "";
}
public String getLoginUserName() {
return loginUserName;
}
public void setLoginUserName(String loginUserName) {
this.loginUserName = loginUserName;
}
public String getLoginPassword() {
return loginPassword;
}
public void setLoginPassword(String loginPassword) {
this.loginPassword = loginPassword;
}
}
I want to be able to view the logged user from other areas in the application. I think I am injecting it incorrectly because loggedUser is always null when I am in a different bean for example something like..
#Stateless
#LocalBean
public class HistoryEJB {
#PersistenceContext
EntityManager em;
#ManagedProperty(value = "#{loggedUser}")
private LoggedUser loggedUser;
public LoggedUser getLoggedUser() {
return loggedUser;
}
public void setLoggedUser(LoggedUser loggedUser) {
this.loggedUser = loggedUser;
}
public void testLoggedUser() {
loggedUser.getLoggedUser();
// Just an example but would be null here - why?
}
}
How can I access this property from other areas in my application? Thanks for any help.
You can't use #ManagedProperty in an EJB and you shouldn't inject a view component into a business-tier component, period. #ManagedProperty is strictly web-tier stuff and is able to inject only and into web-tier, JSF components.
Your EJB ought to have a method that accepts a LoggedUser. This way, you can then pass your logged-in user to the EJB (which is the proper flow of data in a web application). What you have now is just turning best practice on its head.
So
Add a provideLoggedUser(LoggedUser loggedUser) method to your EJB
Call that method on your instance of UserEJB from within your managed bean
Rule of Thumb: Your EJB should not be aware of the web application
It seems you are missing the setter and getter for loggedUser. In principe it is there but it is convention to name it as follows
setProperty
and
setProperty
for a field named property. Note the capital first letter of the field name in the setter and getter!
I have this SessionScoped bean:
#ManagedBean
#SessionScoped
public class LoginBean implements Serializable {
/**
* Creates a new instance of LoginBean
*/
public LoginBean() {
this.usuario = new Usuario();
}
private Usuario usuario;
//getter & setter
}
The Usuario class:
public class Usuario {
public Usuario() {
}
private String password;
private String nombre;
private int idPlanta;
private int nivel;
private String idUsuario;
//getters & setters
}
And I want to get the value of the property idPlanta from the SessionScoped bean (LoginBean) here (in the constructor) see the comments:
#ManagedBean
#ViewScoped
public class PrincipalBean implements Serializable {
public PrincipalBean() {
System.out.println(this.login.getUsuario().getIdPlanta());
//AT THIS POINT THE VALUE OF idPlanta IS 0 but in the session I have 1...
//Method that uses the idPlanta value as a parameter
}
#ManagedProperty(value = "#{loginBean}")
private LoginBean login;
public LoginBean getLogin() {
return login;
}
public void setLogin(LoginBean login) {
this.login = login;
}
}
But when I show the value in the view it shows the value that really is in the Session idPlanta = 1. I dont understand why I cant get the value of that property in the constructor of that ViewScoped bean (PrincipalBean). I show the value in the view here(I know I can get it directly fron the LoginBean but this is just to show that the property login in PrincipalBean has the Session value):
<h:outputText class="titulo" value="Bienvenido(a) #{principalBean.login.usuario.nombre} Planta #{principalBean.login.usuario.idPlanta}" />
The value of idPlanta in PrincipalBean is very important because I use it as a method parameter to show more info when the view is showed.
Please help me. I still learning JSF.
You need to be using these values after the bean has been constructed. When your constructor is called, your bean has net yet been initialzed - therefore the injections have not yet happend. Using the #PostConstruct method you will be able to access the desired values from the injected objects.
For example :
#ManagedBean
#ViewScoped
public class PrincipalBean implements Serializable {
public PrincipalBean() {
}
#PostConstruct
public init() {
System.out.println(this.login.getUsuario().getIdPlanta());
//AT THIS POINT THE VALUE OF idPlanta IS 0 but in the session I have 1...
//Method that uses the idPlanta value as a parameter
}
#ManagedProperty(value = "#{loginBean}")
private LoginBean login;
public LoginBean getLogin() {
return login;
}
public void setLogin(LoginBean login) {
this.login = login;
}
}
See Also
Why use #PostConstruct?
Injecting Managed Beans In JSF 2.0
JSF injection with managed property, good pattern?
Here is my code
Pojo
public class Deal implements Serializable {
private int id;
private String name;
private String description;
private Customer customer;
//getter setter omitted
}
public class Customer implements Serializable {
private int id;
private String name;
private String email;
private String phone;
//getter setter and equal hashcode omitted
}
Managed Bean
#ManagedBean(name="dealBean")
#ViewScoped
public class DealBean implements Serializable {
private List<Customer> customerList;
private List<Deal> dealList;
private Deal deal;
#PostConstruct
public void init() {
deal = new Deal();
dealList = new ArrayList<Deal>();
customerList = new ArrayList<Customer>();
customerList.add(new Customer(1, "MPRL", "mprl#mail.com", "1234455"));
customerList.add(new Customer(2, "Total", "total#mail.com", "3434323"));
customerList.add(new Customer(3, "Petronas", "petronas#mail.com", "8989876"));
}
//getter setter omitted
}
Customer Converter
#FacesConverter("customerConverter")
public class CustomerConverter implements Converter {
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String customerID) {
DealBean dealBean = (DealBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("dealBean");
if (dealBean != null) {
List<Customer> customerList = dealBean.getCustomerList();
for (Customer customer : customerList) {
if (customerID.equals(String.valueOf(customer.getId()))) {
return customer;
}
}
}
return null;
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object obj) {
if (obj != null) {
return String.valueOf(((Customer)obj).getId());
}
return null;
}
}
XHTML
Customer : <h:selectOneMenu id="customer" value="#{dealBean.deal.customer}">
<f:converter converterId="customerConverter" />
<f:selectItems value="#{dealBean.customerList}" var="cus"
itemLabel="#{cus.name}" itemValue="#{cus}" />
</h:selectOneMenu>
When the managed bean is in request or session scope, the Customer pojo is set correctly to Deal pojo. The problem is when the managed bean is in View scope, the Customer pojo is set to Deal pojo as NULL.
I am using JSF 2.2.0
Thanks much for the help in advance.
It's not the converter, is the view scoped the one broken:
Since you're using JSF tags, you cannot use #ViewScoped annotation, because it was removed from specification and recovered only for CDI usage. You could use omnifaces view scoped or the components of apache myFaces (I personally recommend omnifaces).
You can confirm this creating a
System.out.print("Creating");
in the constructor and checking how is called each Ajax request, so the bean is not recovered and since is marked as view and is a partial request, the values are not setted again (unless you send all the form, which is not a nice solution), other workaround could be making the bean request and recover all the data each request, making it Session (but will be alive for the session), or the #ConvesationScoped, in which you'll have to destroy and start the conversation manually.
Again, my first recommendation could be change to a Java ee server compliant and use the CDI annotations since JSF are being depreciated and not updated anymore
I'm currently trying to learn JSF and JPA. I know that the patterns I use are not recommended at all, but I want to understand what's going on because I think it'll help me in the future. I've just thrown together a prototype from various sources.
The problem that I encounter with the setup described below is that apparently the JPA entities are getting detached all the time, which in turn happens because the backing bean gets serialized over and over. In fact, if I remove the Serializable interface from the entity class, I get Exiting serializeView - Could not serialize state: com.sk.Message
Since the entities are detached, nothing gets committed to the database when I call EntityManager.commit(). If I manually merge all the entities (the commented out line in onCellEdit() below) with EntityManager.merge(), the modified entities are committed to the database.
I've already found from other SO posts that I could deal with this problem by adding
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>
to my persistence.xml. But it was also pointed out somewhere that this would only be a workaround and not a solution.
So my questions are:
Is it intended/expected that a #ViewScoped JSF backing bean gets serialized over and over again (while staying on the same view all the time), which makes it difficult to use JPA entities in it?
Is it safe/reasonable to use the SERIALIZE_STATE_IN_SESSION parameter?
As I found recommended many times, should I just forget about JSF managed beans altogether and go with CDI directly (e.g. #ConversationScope to achieve something similar)?
I'm using TomEE (MyFaces, OpenJPA) with PrimeFaces. The backing bean contains the following code:
#ViewScoped
#ManagedBean
public class MessageBean implements Serializable
{
private List<Message> messages;
public List<Message> getMessages()
{
return messages;
}
public void setMessages( List<Message> messages )
{
this.messages = messages;
}
#PostConstruct
public void init()
{
messages = PersistenceManager.getInstance().queryMessages();
}
public void onCellEdit( CellEditEvent event )
{
// PersistenceManager.getInstance().mergeMessages( messages );
PersistenceManager.getInstance().commitTransaction();
}
[...]
A Message is a JPA Entity, like this:
#Entity
#Table( name = "message" )
#NamedQuery( name = "Message.findAll", query = "SELECT a FROM Message a" )
public class Message implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column( unique = true, nullable = false )
private Integer dbid;
#Column( nullable = false, length = 14 )
private String no;
[...]
}
The backing bean is referenced from a JSF page using a PrimeFaces DataTable:
<h:form id="navForm">
<p:dataTable
id="messages"
value="#{messageBean.messages}"
var="message"
editable="true"
editMode="cell">
<f:facet name="header">MESSAGE</f:facet>
<p:ajax
event="cellEdit"
listener="#{messageBean.onCellEdit}"
update=":navForm:messages" />
<p:column>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{message.no}" />
</f:facet>
<f:facet name="input">
<p:inputText
id="modelInput"
value="#{message.no}" />
</f:facet>
</p:cellEditor>
<f:facet name="header">Message number</f:facet>
</p:column>
[...]
I know I'm probably violating dozens of best practices here, but for prototyping I've created a singleton POJO, PersistenceManager, which deals with the JPA interface (and potentially other data sources). I use an application-managed, resource-local EntityManager. An excerpt looks like this:
public class PersistenceManager
{
private static PersistenceManager INSTANCE;
private EntityManagerFactory emf;
private EntityManager em;
private EntityTransaction entr;
private PersistenceManager( PersistenceType persistenceType )
{
emf = Persistence.createEntityManagerFactory( "MessagePU" );
em = emf.createEntityManager();
}
public List<Message> queryMessages()
{
TypedQuery<Message> query = em.createNamedQuery( "Message.findAll", Message.class );
return query.getResultList();
}
public void commitTransaction()
{
if ( entr != null && entr.isActive() )
{
entr.commit();
}
}
[...]
Before committing a transaction you have to start it (then close it at the end of the transaction). Where is the else statement in your commitTransaction method, in case the EntityTransaction object is not active and/or null ?
Plus, I don't see any EJB in your code. The POJO approach is not the best option in an application managed, served, and hosted by a container.
For me, the best approach to implement the persistence layer in JSF and JavaEE applications in general, is the Session Façade Pattern, you can search the web about it, there are plenty of references.
In your case, something like this would do.
A Message Facade, that manages transactions related to the Message entity.
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Stateless
public class MessageFacade extends AbstractFacade<Message> {
#PersistenceContext(unitName = "MessagePU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public MessageFacade() {
super(Message.class);
}
public List<Message> queryMessages()
{
TypedQuery<Message> query = em.createNamedQuery( "Message.findAll", Message.class );
return query.getResultList();
}
}
An abstract facade class implementing generic persistence functions on generic entities.
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public T edit(T entity) {
return getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
Your managed bean would then be something like :
#ViewScoped
#ManagedBean
public class MessageBean implements Serializable
{
#EJB
private MessageFacade messageFacade;
private List<Message> messages;
public List<Message> getMessages()
{
return messages;
}
public void setMessages( List<Message> messages )
{
this.messages = messages;
}
#PostConstruct
public void init()
{
messages = messageFacade.findAll();
}
public void onCellEdit( CellEditEvent event )
{
messageFacade.edit(messages);
}
}
I have a managed bean (SessionScope as follow)
#ManagedBean(name="login")
#SessionScoped
public class Login implements Serializable {
private String userSession;
public Login(){
}
}
In this managedbean, somewhere in the login function, i store the email as a session.
I have another managed bean called ChangePassword (ViewScoped). I need to access the value of the email which is stored in the userSession.
The reason of doing so is that i need to find out the current userSession(email) before i can complete the change password function. (Need change password for that specific email)
How do i do so? New to JSF, appreciate any help!
Just inject the one bean as a managed property of the other bean.
#ManagedBean
#ViewScoped
public class ChangePassword {
#ManagedProperty("#{login}")
private Login login; // +setter (no getter!)
public void submit() {
// ... (the login bean is available here)
}
// ...
}
See also:
Communication in JSF 2.0 - Injecting managed beans in each other
In JSF2, I usually use a method like this:
public static Object getSessionObject(String objName) {
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext extCtx = ctx.getExternalContext();
Map<String, Object> sessionMap = extCtx.getSessionMap();
return sessionMap.get(objName);
}
The input parameter is the name of your bean.
if your session scoped bean is like this :
#ManagedBean(name="login")
#SessionScoped
public class Login implements Serializable {
private String userSession;
public Login(){
}
}
you can access the values of this bean like :
#ManagedBean(name="changePassword")
#ViewScoped
public class ChangePassword implements Serializable {
#ManagedProperty(value="#{login.userSession}")
private String userSession;
public ChangePassword (){
}
}
public static Object getSessionObj(String id) {
return FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(id);
}
public static void setSessionObj(String id,Object obj){
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(id, obj);
}
Add them in your managed bean :