Passing Managedbean property - jsf-2.2

I've two session scoped beans I need to pass values between them through f:setPropertyActionListener but I cant read it from receivable end.
<p:selectOneListbox style="height: 100%; width: 100%" id="lstSubject" required="true" requiredMessage="Please select any Subject"
value="#{chooseSubExamManagedBean.subId}" >
<f:selectItems value="#{chooseSubExamManagedBean.mapSubjects}" />
</p:selectOneListbox>
user chooses the subject and I've to pass this id from p:command button to another bean
<p:commandButton id="cmdProceed" value="Proceed" action="#{chooseSubExamManagedBean.gotoFillMarks}" >
<f:setPropertyActionListener target="#{fillMarksManagedBean.subId}" value="#{chooseSubExamManagedBean.subId}" />
</p:commandButton>
the managed bean fillMarksManagedBean
#Named(value = "fillMarksManagedBean")
#javax.enterprise.context.SessionScoped
public class FillMarksManagedBean implements Serializable{
private int SubId;
private String ExamDetail;
public void setSubId(int SubId) {
this.SubId = SubId;
}
public int getSubExamId() {
return SubExamId;
}
and use that subId in
#PostConstruct
public void init() {
ExamDetail = clsFillMarks.getExamDetail(SubId);
}
...
How do i do this?
Thanks in advance

Related

p:PickList Custom JSF Converter in Spring Boot

I am currently getting
ClassCastException : com.singtel.eshop.converter.PickListConverter cannot be cast to javax.faces.component.UIComponent when using a custom JSF converter with p:pickList .
I am using :
Primefaces 4, JSF 2.2.12 and Spring Boot 2.0.3
The following is my code
Converter
#FacesConverter("PickListConverter")
#Component("PickListConverter")
public class PickListConverter implements Converter {
public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {
PickList p = (PickList)component;
DualListModel dl = (DualListModel)p.getValue();
for (int i = 0; i < dl.getSource().size(); i++) {
if (dl.getSource().get(i).toString().contentEquals(submittedValue)) {
return dl.getSource().get(i);
}
}
for (int i = 0; i < dl.getTarget().size(); i++) {
if (dl.getTarget().get(i).toString().contentEquals(submittedValue)) {
return dl.getTarget().get(i);
}
}
return null;
}
public String getAsString(FacesContext facesContext, UIComponent component, Object value) {
PickList p = (PickList) component;
DualListModel dl = (DualListModel) p.getValue();
//return String.valueOf(dl.getSource().indexOf(value));
return value.toString();
}
}
XHTML:
<p:dialog id="addDialog" header="Add Price Plan Scheme" widgetVar="addDlgl"
position="600,100" modal="true" appendToBody="true" height="500" width="550">
<h:form id="addForm">
<p:selectOneMenu id="type"
value="#{bean.label}"
style="width:100px; margin-left:10px;">
<f:selectItems value="#{bean.types}" var="s"
itemValue="#{s.value}" itemLabel="#{s}" />
<p:ajax update="addForm"
listener="#{bean.listener}"
global="false"/>
</p:selectOneMenu>
<h:panelGrid columns="1" cellpadding="0" style="padding-left:25px"
rendered="#{bean.label == 'TEST'}">
<p:pickList id="desc"
value="#{bean.list}"
style="width:250px !important;" var="data"
itemValue="#{data}"
itemLabel="#{data.desc}"
responsive="true"
showSourceFilter="true" showTargetFilter="true"
filterMatchMode="contains"
binding="#{PickListConverter}"
>
</p:pickList>
</h:panelGrid>
Bean
#Component
#Scope(value="session")
public class Bean{
private String label;
private DualListModel<DataBean> list;
}
DataBean
public class DataBean{
private String desc;
private String id;
// getters and setters
}
Remove the
binding="#{PickListConverter}"
From the picklist and this error is gone
You just don't add a converter via a binding but via a converter attribute or an f:converter converterId tag
See also
jsf custom converter

JSF2.0 popup show after the second click

I have 3 managebean one model and 2 controllers (1 for the popup text) i want a popup after i insert into the database.
my page is like this the problem is that when i call for mensaje.mostrar() i works but when i try to call cursoControlador.registrarCurso() and from there try to call mensaje.mostrar() that changes the value from mostrarMensaje (boolean) don't show the popup.
<ui:define name="centro">
<h:form>
<h:panelGrid columns="3" cellpadding="5">
<p:outputLabel value="Nombre" />
<p:inputText value="#{cursoModelo.nombre}"/>
this is the button use and works fine
<p:commandButton action="#{mesaje.mostrar()}" value="Registrar Curso" >
<f:ajax render="#form"/>
</p:commandButton>
and this is the behavior i want
<p:commandButton action="#{cursoControlador.registrarCurso()}" value="Registrar Curso" >
<f:ajax render="#form"/>
</p:commandButton>
and this is the popup message i want to show
</h:panelGrid>
<h:panelGroup layout="block" styleClass="fondo-popup" rendered="#{mensaje.mostrarMensaje}">
<div class="panel-popup">
<p:outputLabel value="#{mensaje.texto}"/>
<h:commandButton value="Aceptar" action="#{mensaje.esconder()}">
<f:ajax render="#form"/>
</h:commandButton>
</div>
</h:panelGroup>
</h:form>
</ui:define>
model
#Named(value = "cursoModelo")
#SessionScoped
public class CursoModelo implements Serializable {
private String nombre;
//getters and setters...
}
controller 1
#Named(value = "cursoControlador")
#SessionScoped
public class CursoControlador implements Serializable{
#Inject private CursoModelo cursoModelo;
#Inject private Mensaje mensaje;
/**
* Creates a new instance of CursoControlador
*/
public CursoControlador() {
}
public String registrarCurso(){
//SOME CODE that inserts into de database
mensaje.mostrar(); //this is the problem probably i'm doing it wrong
return "index";
}
}
controller 2 (The controller for the message)
#Named(value = "mensaje")
#SessionScoped
public class Mensaje implements Serializable {
private String texto;
private boolean mostrarMensaje;
/**
* Creates a new instance of Mensaje
*/
public Mensaje() {
texto = "Mensaje a mostrar";
mostrarMensaje = false;
}
public void mostrar(){
mostrarMensaje = true;
}
public void esconder(){
mostrarMensaje = false;
}
//getters and setters from texto and mostrarMensaje
}

JSF rendered h:commandLink ajax not working [duplicate]

The reason why the topic has "kind of" is because I have an example in JSF 2.2 where I use a commandButton and call a bean function twice (depending on the url). It's basically the same code, which executes only in one example.
Here's the code with the description of the "error" below the code:
User bean
#ManagedBean
#RequestScoped
public class User {
private String name;
private String surname;
private int age;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public User(String name, String surname, int age, int id) {
super();
this.name = name;
this.surname = surname;
this.age = age;
this.id = id;
}
public User(){}
}
UsersBean bean:
#ManagedBean
#SessionScoped
public class UsersBean {
private List<User> listOfUsers = new ArrayList<User>();
private String passedParameter;
public UsersBean() {
listOfUsers.add(new User("Tywin", "Lannister", 60, 1));
listOfUsers.add(new User("Tyrion", "Lannister", 30, 2));
listOfUsers.add(new User("Jaime", "Lannister", 31, 3));
listOfUsers.add(new User("Cercei", "Lannister", 29, 4));
listOfUsers.add(new User("John", "Snow", 31, 5));
}
public List<User> getAll() {
System.out.println("getAall is called.");
return listOfUsers;
}
public User getDetails() {
passedParameter = (String) FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get("userID");
int id = Integer.parseInt(passedParameter);
User selected = null;
for (User u : listOfUsers) {
if (u.getId() == id) {
selected = u;
}
}
return selected;
}
public String addUser(User u) {
System.out.println("addUser is called.");
if (u.getId() != 0) {
for (User edit : listOfUsers) {
if (edit.getId() == u.getId()) {
System.out.println("Found it!");
edit.setAge(u.getAge());
edit.setName(u.getName());
edit.setSurname(u.getSurname());
}
}
} else {
u.setId(listOfUsers.size() + 1);
listOfUsers.add(u);
}
return "";
}
}
users.xhtml:
<f:view>
<!-- http://stackoverflow.com/questions/8083469/method-must-have-signature-string-method-etc-but-has-signature-void -->
<h:dataTable value="#{usersBean.all}" var="u">
<h:column>
<f:facet name="header">
User ID
</f:facet>
#{u.id}
</h:column>
<h:column>
<f:facet name="header">
Name
</f:facet>
#{u.name}
</h:column>
<h:column>
<f:facet name="header">
Details
</f:facet>
<h:link outcome="users" value="edit user">
<f:param name="userID" value="#{u.id}"></f:param>
<f:param name="action" value="edit"></f:param>
</h:link>
<h:link outcome="usersDetails" value="get details">
<f:param name="userID" value="#{u.id}"></f:param>
</h:link>
</h:column>
</h:dataTable>
<h:panelGroup rendered="#{param['action'] == 'edit'}">
<h1>Edit!</h1>
<h:form>
<ui:param name="editUser" value="#{usersBean.details}"></ui:param>
<h:outputText value="Name"></h:outputText>
<h:inputText value="#{editUser.name}"></h:inputText> <br />
<h:outputText value="Surname"></h:outputText>
<h:inputText value="#{editUser.surname}"></h:inputText> <br />
<h:outputText value="Age"></h:outputText>
<h:inputText value="#{editUser.age}"></h:inputText> <br />
<h:commandButton action="#{usersBean.addUser(editUser)}" value="Edit" type="submit"> </h:commandButton>
</h:form>
</h:panelGroup>
<h:panelGroup rendered="#{empty param['action']}">
<h1>Add!</h1>
<h:form>
<h:outputText value="Name"></h:outputText>
<h:inputText value="#{user.name}"></h:inputText>
<h:outputText value="Surname"></h:outputText>
<h:inputText value="#{user.surname}"></h:inputText>
<h:outputText value="Age"></h:outputText>
<h:inputText value="#{user.age}"></h:inputText>
<h:commandButton action="#{usersBean.addUser(user)}" value="Add" type="submit"></h:commandButton>
</h:form>
</h:panelGroup>
</f:view>
OK, so, everything works perfectly. usersBean.addUser adds the user. If I add another inputText for ID and I put in an existing ID, the corresponding function updates the values. So, addUser function works as expected.
The problem is in case of
<h:panelGroup rendered="#{param['action'] == 'edit'}">
as you can see in the xhtml above, the code is basically the same, with the sole exception that I fill in the data of the user that was selected. This works, I get the appropriate data into input fields, but when I change them and click Edit, nothing happens. The function is not called! whereas in case of add, the function is called and it works.
It appears as if there is no action defined in case of edit, it only reloads the page (submit) without the actual action addUser.
How is this caused and how can I solve it?
It's because #{param['action'] == 'edit'} didn't evaluate true during processing the form submit and therefore the <h:panelGroup> is basically not rendered during processing the form submit, including the <h:commandButton> sitting in there. The form submit namely did not pass that parameter back to JSF. This way JSF won't see the <h:commandButton> and therefore never be able to decode and queue its action event. You need to make sure that all your rendered conditions evaluate the same during processing the form submit as they were during displaying the form (this is part of JSF's safeguard against tampered/hacked requests wherein the enduser would otherwise be able to execute unrendered command buttons like admin-only buttons).
So, you basically need to retain that parameter during the postbacks as well so that the rendered expression still evaluates true during processing the form submit. This can be achieved in several ways:
Add it as <f:param> inside the <h:commandButton> of relevance:
<h:commandButton action="#{usersBean.addUser(editUser)}" value="Edit" type="submit">
<f:param name="action" value="#{param.action}" />
</h:commandButton>
(note: param['action'] and param.action are equivalent; those brackets are only useful if the 'action' contains periods, or represents another variable)
Set it as a bean property by <f:viewParam>. Requirement is that the bean needs to be in view scope or broader. You've it in the session scope already, which is okay (but which is IMO way too broad, but that aside):
<f:metadata>
<f:viewParam name="action" value="#{usersBean.action}" />
</f:metadata>
...
<h:panelGroup rendered="#{usersBean.action}">
...
</h:panelGroup>
If you're already using JSF utility library OmniFaces, use its <o:form> instead of <h:form> which enables you submit to the current request URI instead of to the current JSF view ID. This way the GET request string will automagically be retained and you don't need to copypaste <f:param> over all command buttons like as in #1:
<o:form useRequestURI="true">
...
</o:form>
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated - point 6

Conditional required in jsf 2 when FacesConverter involved

I have a form like this:
<h:form>
Phone number:
<h:inputText id="phone_number"
value="#{dbUserManager.phoneNumber}"
validatorMessage="The phone number is invalid."
required="#{auth.value eq 'MOBILE'}"
requiredMessage="Phone number is required." />
</h:inputText>
Authentication type:
<h:selectOneMenu value="#{dbUserManager.authentication}" converter="#{authenticationTypeConverter}" binding="#{auth}">
<f:selectItems value="#{dbUserManager.authTypeList}" />
</h:selectOneMenu>
</h:form>
AuthenticationType is an entity similar to this:
#Entity
public class AuthenticationType implements Serializable
{
#Id
#Basic(optional = false)
private Short id;
#Basic(optional = false)
private String description;
#Override
//...
public String toString()
{
return description;
}
and finally AuthenticationTypeConverter:
#Stateless
#ManagedBean
#FacesConverter(value="authenticationTypesConverter")
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class AuthenticationTypeConverter implements Converter
{
#PersistenceContext(unitName="pu")
private EntityManager em = null;
#Override
public Object getAsObject(FacesContext fc, UIComponent uic, String string)
{
TypedQuery<AuthenticationType> q = em.createNamedQuery(
AuthenticationType.FIND_BY_DESCRIPTION,
AuthenticationType.class);
q.setParameter("description", string);
return q.getSingleResult();
}
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object o)
{
if (o == null)
{
return "";
}
return o.toString();
}
}
What I tried to do is that to set the required of phone number to true when authentication type is set to 'MOBILE'. But it's not behaving as I expect.
I think the problem lies in the fact that I need to use FacesConverter for AuthenticationType. But I don't know how to solve it.
Can anyone give a hint?
Thanks
You have to rerender the h:inputText-field after the user chose from your h:selectOneMenu. To do so, change this selection to
<h:selectOneMenu value="#{dbUserManager.authentication}"
converter="#{authenticationTypeConverter}" binding="#{auth}">
<f:selectItems value="#{dbUserManager.authTypeList}" />
<f:ajax event="change" render="phone_number" />
</h:selectOneMenu>
Also in the inputTexts required-attribute I would expect something more like
{dbUserManager.authentication.description}
Give it a try...
Update 2014/01/22:
If you want to hold already typed informations in the phone_number field, you can tell the <f:ajax> tag to execute not only selectOneMenu but also the input field before rendering it new. In this case replace the upper <f:ajax /> solution with
...
<f:ajax event="change" execute="#this phone_number" render="phone_number" />
...

Clicking on commandLink is invoking preRenderView again

In my facelet, I have the below commandLink:
<h:form>
<p:commandLink id="excelExport" action="#{studentBean.exportReport()}" ajax="false">
<f:param name="type" value="EXCEL" />
<p:graphicImage library="img" name="excel.png" width="20" />
</p:commandLink>
</h:form>
This is what I am having in my backing bean:
#ManagedBean
#RequestScoped
public class StudentBean implements Serializable {
.............
#ManagedProperty(value = "#{param.type}")
private String typeOfExport;
.............
public void preRender(ComponentSystemEvent event) {
System.out.println("Inside prerender");
if (FacesHelper.isAjaxRequest()) {
return;
}
}
.............
public void exportReport() {
System.out.println("Type of Report is: " + typeOfExport);
}
}
Now I would like to execute the method exportReport once I click on the commandLink. But what is happening here is that after executing the method, it is going to preRender again. I don't want to render the entire form again. Any idea what mistake I am doing here?

Resources