Service not injected in ActionListener - jsf

I'm having a problem regarding actionlistener in my project. I'm creating a website but my problem is at the login and I'm using composite and JSF. Whenever I try to login I get a nullpointer pointing at the actionlistener class line 30 which is in the if statement.
ActionListener class
public class LoginActionListener implements ActionListener {
#Inject private Service service;
#Override
public void processAction(ActionEvent event) throws AbortProcessingException {
UIComponent container = event.getComponent().getNamingContainer();
String username = (String) ((UIInput)
container.findComponent("form:username")).getValue();
String pwd = (String) ((UIInput)
container.findComponent("form:password")).getValue();
if(service.isRegistered(username, pwd))
return;
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(container.getClientId(),
new FacesMessage("Username and password are invalid. Please try again."));
throw new AbortProcessingException("Invalid credentials");
}
}
Service class
public boolean isRegistered(String username, String password){
for (User u : users) {
if (u.getUserName().equals(username) && u.getPassword().equals(password))
return true;
}
return false;
}
Composite login xhtml file
http://blg.nikonsrc.com/image/4nEwBZn2a6VnBoCaET-wUiU_iwnRwLBaMfMR67ypIKVyameRSjNcbAmtoKug6n4_PWUXZcEFpp8/item.JPG?rot=0
http://blg.nikonsrc.com/image/4nEwBZn2a6VnBoCaET-wUiU_iwnRwLBaMfMR67ypIKU7KIV8XlnDFQmtoKug6n4_PWUXZcEFpp8/item.JPG?rot=0
Best regards
Jakob

If your service is null it seems to be a problem with injecting your Service class. Check if the Service class has proper annotations which allows that class to be injected. Be aware that you should use annotations form one package:
For CDI-based bean definitions
javax.enterprise.context.SessionScoped
javax.inject.Named
javax.inject.Inject
For JSF-based bean definitions
javax.faces.bean.SessionScoped
javax.faces.bean.ManagedBean
javax.faces.bean.ManagedProperty
For example:
#Named
#SessionScoped
public class Service {
...
public boolean isRegistered(String username, String password){
for (User u : users) {
if (u.getUserName().equals(username) && u.getPassword().equals(password))
return true;
}
return false;
}
}

Related

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!

Stateful EJB does not keep property value

I am using a stateful EJB for keeping my login information:
#Stateful
public class SecurityService {
private static final Logger log4jLogger = Logger.getLogger(SecurityService.class);
#Inject UtenteDao utenteDao;
#Inject AutorizzazioneDao autorizzazioneDao;
private Utente utenteCorrente;
private Negozio negozioCorrente;
public SecurityService() {
}
public boolean authenticate() {
boolean result = false;
Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
if (principal!=null) {
utenteCorrente = utenteDao.findByUsername(principal.getName());
}
if (negozioCorrente!=null && utenteCorrente!=null) {
Autorizzazione a = autorizzazioneDao.cercaPerNegozioAndUtente(negozioCorrente, utenteCorrente);
result = a!=null;
}
return result;
}
// ...
}
My JSF login page is controlled by:
#Named
#RequestScoped
public class LoginController {
#Inject private SecurityService securityService;
private String username;
private String password;
private Negozio negozio;
public void login() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
try {
if (request.getUserPrincipal() != null) {
request.logout();
}
request.login(username, password);
securityService.setNegozioCorrente(negozio);
if (!securityService.authenticate()) {
throw new ServletException("Utente non abilitato.");
}
externalContext.redirect("/pippo/");
} catch (ServletException e) {
e.printStackTrace();
context.addMessage(null, new FacesMessage("Accesso Negato"));
}
}
public void logout() throws IOException {
//...
}
public String getLoggedUsername() {
Utente utenteCorrente = securityService.getUtenteCorrente();
String fullName = "";
if (utenteCorrente!=null) {
fullName = utenteCorrente.getNomeCompleto();
} else {
System.out.println("Utente NULLO");
}
return fullName;
}
//...
}
My users actually can login the way I want (programmatic security with some adds from my domain).
The problem I have is in the next page, when you're already logged in. I want to display in all pages header "Welcome! You're logged in as #{loginController.loggedUsername}.
I keep getting a null securityService.getUtenteCorrente().
SecurityService EJB behaves like a Stateless session bean! I want to know whether I am misunderstanding something about the Stateful EJBs, or I just omitted something for this to work as I expect.
My goal is just to have a "session-wide" bean for keeping user state. Is a EJB necessary or can I just use a SessionScoped JSF ManagedBean?
LoginController is request-scoped and your SecurityService is dependent-scoped (for all purposes it is not session-scoped unless you specify it as such). Therefore, when the second JSF page references the LoginController in a EL expression, a new instance of LoginController would be created that would have a reference to a different instance of the SecurityService SFSB.
If you need to access the original SecurityService instance, you should mark it as #SessionScoped so that clients like the LoginController can access them across requests. But then, you might also want to consider why you need a #Stateful annotation in the first place, since this task could be done by an #SessionScoped managed bean. You don't really need a SFSB to store a reference to your User/Principal objects.
In order to be managed session beans must be declared using the #EJB annotation or looked up using the JNDI, the way you inject it just gives you a plain object not managed by the app server, in fact you create a new object any time you use it.

How to access property of one managed bean in another managed bean

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 :

How to get number of connected users and their role using j_security_check?

I get the username of the connected user (using j_security_check) this way, through a managed bean:
......
username = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal().getName();
And then display it in a jsf page this way : #{userBean.username}
But I figured no way to get the number of connected users and get their role.
In other words, I want to display besides the username, the user role and the number of connected users.
How can I achieve this!?
Thanks in advance for your help!
EDIT:
I can now get the Role of the connected user, using a namedquery in a managed bean :
public Users getUserRole(){
try {
Users auser = (Users)
em.createNamedQuery("Users.findByUsername").
setParameter("username", getRemoteUser()).getSingleResult();
return auser;
} catch (NoResultException nre) {
JsfUtil.addErrorMessage(nre, "getUserRole Error");
return null;
}
}
and in the xhtml page:
<h:outputLabel for="rolefacet" value="Role: "/>
<h:outputFormat id="rolefacet" value="#{UserBean.userRole.ugroup}" />
while ugroup is the role name in the Users entity class.
EDIT: One solution that still does not work for me is to add a HttpSessionListener to my web.xml:
package beans;
/**
*
* #author med81
*/
import java.io.Serializable;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.ArrayList;
import javax.faces.context.FacesContext;
public class SessionCounter implements Serializable, HttpSessionListener {
private List sessions = new ArrayList();
Object s = FacesContext.getCurrentInstance().getExternalContext().getSession(false);
public Object getS() {
return s;
}
public void setS(Object s) {
this.s = s;
}
public SessionCounter() {
}
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
sessions.add(session.getId());
session.setAttribute("counter", this);
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
sessions.remove(session.getId());
session.setAttribute("counter", this);
}
/**
*
* #return size of the session list
*/
public int getActiveSessionNumber() {
return sessions.size();
}
}
Here's a basic kickoff example how you could do it when you're on Servlet 3.0 and thus are able to utilize programmatic login by the new HttpServletRequest#login() API.
The login form: login.xhtml
<h:form>
<h:inputText value="#{user.username}" />
<h:inputSecret value="#{user.password}" />
<h:commandButton value="Login" action="#{user.login}" />
<h:messages />
</h:form>
The user manager bean: com.example.UserManager
#ManagedBean(name="user")
#SessionScoped
public class UserManager implements Serializable {
private String username;
private String password;
private User current;
#EJB
private UserService userService;
#ManagedProperty("#{loginManager.logins}")
private Set<User> logins;
public String login() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.login(username, password);
current = userService.find(username, password);
} catch (ServletException e) {
// Unknown login. Will be handled later in current==null check.
}
if (current == null) {
context.addMessage(null, new FacesMessage("Unknown login"));
return null;
} else {
logins.add(current)
return "home?faces-redirect=true";
}
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "login?faces-redirect=true";
}
// ...
}
The logout (and session invalidate) listener: com.example.LogoutListener
#WebListener
public class LogoutListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent event) {
// NOOP.
}
#Override
public void sessionDestroyed(HttpSessionEvent event) {
UserManager userManager = (UserManager) event.getSession().getAttribute("user");
if (userManager != null && userManager.getCurrent() != null) {
userManager.getLogins().remove(userManager.getCurrent());
}
}
}
(Do not do this in logout() method! It's the session invalidation which triggers this, the session invalidation will take place when logout() is called OR when session has expired)
In any logged-in view you can obtain the current user and the login count as follows:
<p>Welcome, #{user.current.name}!</p>
<p>Total logged in users: #{user.logins.size()}</p>
get the number of connected users
I'll assume that you mean to get the number of logged-in users.
Basically, you need to have an applicationwide Set<User> with all logged-in users and add the User to it when it logs in and remove the User when it logs out or when its session is destroyed. Here's an example which uses an application scoped managed bean
#ManagedBean(eager=true)
#ApplicationScoped
public class LoginManager implements Serializable {
private Set<User> users = new HashSet<User>();
public Set<User> getUsers() {
return users;
}
}
If you were using Java EE 6 it would have been easy to replace j_security_check by a managed bean method which utilizes the new Servlet 3.0 HttpServletRequest#login() and simultaneously adds the User to the Set<User> of the injected LoginManager bean.
But on Java EE 5 there is no trivial way to hook on it. You would need to check every request for the logged-in user. Best to achieve this is to put the User object in the session whenever there's an UserPrincipal. You can do this using a filter which does roughly the following job in doFilter() method.
UserPrincipal principal = request.getUserPrincipal();
User user = (User) session.getAttribute("user");
if (principal != null && user == null) {
user = userService.findByName(principal.getName());
session.setAttribute("user", user);
LoginManager loginManager = (LoginManager) servletContext.getAttribute("loginManager");
loginManager.getUsers().add(user);
}
Finally, to remove the user from the logins, best is to hook on HttpSessionListener#sessionDestroyed(), assuming that you're invalidating the session on logout. This will also be called when the session expires.
public void sessionDestroyed(HttpSessionEvent event) {
User user = (User) event.getSession().getAttribute("user");
if (user != null) {
LoginManager loginManager = (LoginManager) event.getSession().getServletContext().getAttribute("loginManager");
loginManager.getUsers().remove(user);
}
}

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