How to Inject ManagedBeans in JSF2.0 - jsf

I have got Controller-ManagedBeans and Model-ManagedBeans (like MVC-Pattern).
Here my Controller:
#ManagedBean
#RequestScoped
public class ProjectController {
private ProjectData projectBean; //The Model-ManagedBean (see below)!
private IProjectService projectService; //My Service-Layer
public ProjectController(){
init();
}
private void init(){
projectBean = new ProjectData();
projectService = new ProjectService();
}
public String saveProject() {
projectService.addProject(projectBean.getProjectDTO());
return ("");
}
}
...and her you can see my model, which gets its values out of a facelet...
#ManagedBean(name="ProjectData")
#SessionScoped
public class ProjectData {
private ProjectDTO projectDTO;
public ProjectData(){
projectDTO = new ProjectDTO();
}
public ProjectDTO getProjectDTO() {
return projectDTO;
}
public void setProjectDTO(ProjectDTO projectDTO) {
this.projectDTO = projectDTO;
}
public String getTitle() {
return projectDTO.getTitle();
}
public void setTitle(String title) {
projectDTO.setTitle(title);
}
}
My problem is now that it doesn't work. I think I need to inject the dependency between those two classes. But how? Is there a JSF-pro that can help me.
I would like to use annotations.
Thanks
Update after BalusC's post
I changed my code a little bit, but it still doesn't work. Any further advice, please.
#ManagedBean(name="projectData")
#SessionScoped
public class ProjectData {
...
#ManagedProperty(value="#{projectData}")
private ProjectData projectData;
The error com.sun.faces.mgbean.ManagedBeanCreationException says that the controller bean can not be created because projectData (the model-bean) is not found..

This should work:
#ManagedProperty(value="#{ProjectData}")
private ProjectData projectBean
That said, the normal practice is to start instance names with a lowercase. You also don't do in real
ProjectData ProjectData = new ProjectData();
but rather
ProjectData projectData = new ProjectData();
If you omit the (name="ProjectData") from the #ManagedBean, then it will automatically default to projectData.
As per your update:
The error com.sun.faces.mgbean.ManagedBeanCreationException says that the controller bean can not be created because projectData (the model-bean) is not found.
It's actually more telling that property projectData cannot be found. The property is not writable. In other words, the setter is missing. In the future please don't rephrase error messages and just copypaste them.

Okay guys I have found the answer:
there are missing get and set methods in my controller:
/*
* Getter and Setter
*/
public ProjectData getProjectData() {
return projectData;
}
public void setProjectData(ProjectData projectData) {
this.projectData = projectData;
}
Reference

Related

Why is my Primefaces.current() returning null

So, I have this page:
#Named("ManagementPage")
#ViewScoped
#Getter
#Setter
#Join(path = "/{appScope}/admin/management",
to = "/pages/scoped/managementOverview.xhtml")
#Page(
group = "kitchen",
icon = "mdi mdi-comment-text",
key = "management",
navigation = Page.Navigation.ADMIN_SCOPED,
outcome = "/pages/scoped/managementOverview.xhtml",
auth = #PageAuth(value = "MANAGER_ACCESS", scoped = true))
public class ManagementPage implements Serializable {
private static final long serialVersionUID = 1L;
#Inject
private ManagementModel model;
#PostConstruct
public void init() {
this.model.init();
}
}
It's ViewScoped. And the model for it is:
#Log4j
#Dependent
#Getter
#Setter
public class ManagementModel implements Serializable {
...
}
I want, whenever I receive an event, to refresh some UI on the frontend (I'm using JSF). For that, I've created this dispatcher:
#ApplicationScoped
public class OrderEventDispatcher {
private static final List<ManagementModel> subscriptions = new ArrayList<>();
public static void addSubscriber(ManagementModel subscriber) {
subscriptions.add(subscriber);
}
public static void removeSubscriber(ManagementModel subscriber) {
subscriptions.remove(subscriber);
}
public void observerOrderCreated(#Observes FrontendEvent frontendEvent) {
if(frontendEvent instanceof ContentItemCreatedEvent){
if(!"order".equals(((ContentItemCreatedEvent) frontendEvent).getTypeKey())){
return;
}
}
if(frontendEvent instanceof ContentItemChangedEvent){
if(!"order".equals(((ContentItemChangedEvent) frontendEvent).getTypeKey())){
return;
}
}
subscriptions.forEach(ManagementModel::orderInit);
}
}
(I have implemented a proper equals for this in my model)
For my dispatcher to work, I'm subcribing with my model to it (the methods are inside the model)
#PostConstruct
public void init() {
id = totalIds++;
OrderEventDispatcher.addSubscriber(this);
...
And then i unsubscribe before I destroy the model:
#PreDestroy
public void preDestroy() {
OrderEventDispatcher.removeSubscriber(this);
}
And finally, the methods I call from my dispatcher:
public void orderInit() {
loadMergedOrders();
initializeDonut();
PrimeFaces.current().executeScript("orderInit()");
}
I'm doing all this in order to refresh my page (even when multiple instance of the same page are open) in reaction to an event (some item is created/deleted/modified, of that the FrontendEvent takes care). Now the issue is that my PrimeFaces.current() is always returning null, I've added a breakpoint in the init() method and I tried using PrimeFaces.current() and it worked then, but then when I went through the Dispatcher and into the orderInit() with the debugger I've seen that PrimeFaces.current() now returns null. Does anyone have any idea what I'm doing wrong? If not how to fix this then maybe a different approach to solving this. Thanks for your time!

GSON, #SerializedName not taken into account when class is loaded in different scope

I have created two exactly the same classes in two different packages and two different .jars. the com.test is loaded globally (placed in /lib/ext/) in Tomcat7, while es.package is loaded as a dependency of a portlet.
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class RequestBean implements Serializable {
#SerializedName("SOMETHING")
private String id;
#SerializedName("CUENTA")
private String account;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
When having the following code in the portlet:
com.test.RequestBean localBean = new com.test.RequestBean();
localBean.setAccount("account");
localBean.setId("100");
es.package.RequestBean globalBean = new es.package.RequestBean();
globalBean.setAccount("account");
globalBean.setId("100");
System.out.println(gson.toJson(localBean, localBean.getClass()).toString());
System.out.println(gson.toJson(globalBean, globalBean.getClass()).toString());
To my surprise, the result is different. For the globalBean #SerializedName is not taken into account. What can be the reason that? Global class is available in the global scope and the local one only for the scope of a portlet.
{"SOMETHING":"100","CUENTA":"account"}
{"id":"100","account":"account"}
The reason was gson-2.2.0 loaded in the scope of portlet and gson-3.2.1 in the global. Leaving just the global one fixed this issue.

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?

Access Session Bean Property/Inject Session Bean

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!

JSF - Get the SessionScoped Bean instance

I have this configuration on my web application. 2 beans :
1° Bean - It checks the login;
#ManagedBean(name="login")
#SessionScoped
public class Login {
private String nickname;
private String password;
private boolean isLogged;
public String getNickname() { return nickname; }
public void setNickname(String newValue) { nickname=newValue; }
public String getPassword() { return password; }
public void setPassword(String newValue) { password=newValue; }
public void checkLogin() {
... i check on db the nickname and the password ...
if(USER EXIST) {
isLogged=true;
} else {
isLogged=false;
}
return true;
}
}
2° Bean - Manage User parameter :
#ManagedBean(name="user")
#SessionScoped
public class User {
private String name;
private String surname;
private String mail;
public User() {
String[] record=null;
Database mydb=Configuration.getDatabase();
mydb.connetti();
ArrayList<String[]> db_result=null;
db_result=mydb.selectQuery("SELECT name, surname, mail, domicilio FROM users WHERE nickname='???????'");
int i = 0;
while (i<db_result.size() ) {
record=(String[]) db_result.get(i);
i++;
}
}
... getter and setter methods...
}
As you can see, I would like to know how get the nickname setted previously on my login bean, so i can do the query on my DB.
In fact i need to get the instance of the current-session bean login : how can I get it? I should use somethings like session.getBean("login") :)
Hope this question is clear :)
Use #ManagedProperty to inject it and use #PostConstruct to access it after bean's construction (because in a normal constructor it would be still null).
#ManagedBean
#SessionScoped
public class User {
#ManagedProperty(value="#{login}")
private Login login;
#PostConstruct
public void init() {
// Put original constructor code here.
}
// Add/generate getters/setters and other boilerplate.
}
That said, this is not the correct approach. You'd like to do it the other way round. Inject User in Login by #ManagedProperty(value="#{user}") and do the job during submit action method.
You'd also like to put the password in WHERE clause as well. There's absolutely no need to haul the entire users table into Java's memory and determine it one by one. Just let the DB do the job and check if it returns zero or one row.
Also try using the following code:
ExternalContext tmpEC;
Map sMap;
tmpEC = FacesContext.getCurrentInstance().getExternalContext();
sMap = tmpEC.getSessionMap();
login loginBean = (login) sMap.get("login");

Resources