I wanted process data from other bean, in ActionListener method, but it throw NullPointerException
, so i try resafe instance of bean to next instance in init() method with @PostConstruct
annotation, but it still throw NullPointerException
. I know that can obtain bean throught FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(context, expression, expectedType);
but is it possible throught @ManagedProperty
? This is the code:
Login.java
package sklad;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedProperty;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
public class Login implements ActionListener{
private Osoba os;
@ManagedProperty(value="#{osoba}")
private Osoba osoba;
@PostConstruct
public void init(){
os = osoba;
}
@Override
public void processAction(ActionEvent a) throws AbortProcessingException {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage("zprava", new FacesMessage(os.getId().toString() + " " + os.getHeslo()));
}
public Osoba getOsoba() {
return osoba;
}
public void setOsoba(Osoba osoba) {
this.osoba = osoba;
}
public Osoba getOs() {
return os;
}
public void setOs(Osoba os) {
this.os = os;
}
}
Osoba.java
package sklad;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
@ManagedBean
@SessionScoped
public class Osoba{
private Integer id;
private String heslo;
public Osoba(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getHeslo() {
return heslo;
}
public void setHeslo(String heslo) {
this.heslo = heslo;
}
}
login.xhtml
<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>title</title>
<link rel="stylesheet" type="text/css" href="../styles/login.css" />
</h:head>
<h:body>
<p:growl id="growl" showDetail="true" life="3000" />
<p:panel id="panel_login" header="Přihlášení" styleClass="panel">
<p:panelGrid styleClass="panelGrid">
<h:form>
<p:row>
<p:column>
<h:outputText value="ID: " />
</p:column>
<p:column>
<h:inputText id="id_login" value="${osoba.id}" />
</p:column>
</p:row>
<p:row>
<p:column>
<h:outputText value="Heslo: " />
</p:column>
<p:column>
<h:inputSecret id="heslo_login" value="${osoba.heslo}" />
</p:column>
</p:row>
<p:row>
<p:column colspan="2">
<h:commandButton id="btn_login" value="Přihlásit">
<f:actionListener type="sklad.Login"/>
</h:commandButton>
</p:column>
</p:row>
</h:form>
</p:panelGrid>
</p:panel>
</h:body>
</html>
The more traditional way of invoking an action listener is to use a method binding, like so:
@ManagedBean
@RequestScoped
public class Login {
...
public void doLogin(ActionEvent event){
// handle action
}
}
And then in the button:
<h:commandButton id="btn_login" value="Přihlásit" actionListener="#{login.doLogin}"/>
This approach has the benefit of turning Login
into a ManagedBean, which will make it so the annotations on it will be processed by JSF - and that makes the @ManagedProperty
annotation work as expected.