I´m with a strange problem. I´m using the picklist component but it seems like when I use the picklist my commandbutton stop working: Here´s the code:
xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>PickList Test</title>
</h:head>
<h:body>
<h:form id="form">
<p:pickList value="#{pickListBean.employeeList}" var="employee" itemLabel="#{employee.employeeName}" itemValue="#{employee.employeeCode}" />
<p:commandButton value="Save" action="#{pickListBean.message}" style="margin-left: 12px;"/>
</h:form>
</h:body>
</html>
bean
#ManagedBean
#RequestScoped
public class PickListBean {
#EJB
private BussinessList bl = new BussinessList();
private DualListModel<Employee> employeeList;
private Employee employee;
/**
* Creates a new instance of PickListBean
*/
public PickListBean() {
List<Employee> source = new ArrayList<Employee>();
List<Employee> target = new ArrayList<Employee>();
source = bl.getEmployee();
employeeList = new DualListModel<Employee>(source, target);
}
public void message(){
System.out.println("CommandButton is working");
}
public DualListModel<Employee> getEmployeeList() {
return employeeList;
}
public void setEmployeeList(DualListModel<Employee> employeeList) {
this.employeeList = employeeList;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee= employee;
}
}
When I click in the commandbutton the message method is not called, but when I remove the picklist from my xhtml the commandbutton call the message method.
I´m using jsf 2.2, primefaces 4.0...
Lots of errors on this code
Before starting with the errors, I can see 2 seriously poor naming choices in the method named getEmployeePickList
It's not a PickList in the first place. its a DataList
the difference from EmployeeList is that it keeps instances of Employee instead of Functionario. The names you chose, give the impression that one of them is a PickList, while the other is an ArrayList, and they keep instances of the same Class
Now, your xhtml might missing something in the declarations. I tried your code, and even when i deleted the pickList, your commandbutton would not fire. Try starting with this (drop the xml declaration)
<!DOCTYPE html PUBLIC "-W3CDTD XHTML 1.0 TransitionalEN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
Also, the Employee Class is not a String, so your pickList will not work without a converter. See this for example
Finally, your PickList will search for a setEmployeePickList() method in your Class. I tried using your pickList working with String instead of Employee, to get past the converter issue, and naturally, I got this error:
javax.el.PropertyNotFoundException: test.xhtml #21,140 value="#{pickListBean.employeePickList}": Property 'employeePickList' not writable on type org.primefaces.model.DualListModel
The solution for this, would be , feeding the pickList with #{pickListBean.employeeList} instead of #{pickListBean.employeePickList}. You can populate your Employee List somewhere else, like in the PickListBean constructor, instead of re-creating in getEmployeePickList.
Related
I'm trying to make a page where the user can insert one or more Providers, check all the Providers inserted, then confirm. ONLY when the user confirms, all the Providers inserted will be stored in my Database.
How can I do that? It seems that if I use my ManagedBean Controller, with List where I will store the Providers, I get a strange error
HTTP Status 500 -
root cause
java.lang.NullPointerException
it.myProject.model.Provider.equals(Provider.java:71)
org.apache.myfaces.shared.util.SelectItemsIterator.next(SelectItemsIterator.java:275)
org.apache.myfaces.shared.util.SelectItemsIterator.next(SelectItemsIterator.java:49)
org.apache.myfaces.shared.renderkit.RendererUtils.internalGetSelectItemList(RendererUtils.java:800)
org.apache.myfaces.shared.renderkit.RendererUtils.getSelectItemList(RendererUtils.java:764)
org.apache.myfaces.shared.renderkit.html.HtmlSelectableRendererBase.internalRenderSelect(HtmlSelectableRendererBase.java:74)
org.apache.myfaces.shared.renderkit.html.HtmlMenuRendererBase.renderMenu(HtmlMenuRendererBase.java:91)
org.apache.myfaces.shared.renderkit.html.HtmlMenuRendererBase.encodeEnd(HtmlMenuRendererBase.java:76)
javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:665)
javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:545)
javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:541)
javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:541)
org.apache.myfaces.shared.view.JspViewDeclarationLanguageBase.actuallyRenderView(JspViewDeclarationLanguageBase.java:364)
org.apache.myfaces.shared.view.JspViewDeclarationLanguageBase.renderView(JspViewDeclarationLanguageBase.java:201)
org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:285)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:59)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:59)
org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:116)
org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
here's the code of my ProviderController
#ManagedBean
public class ProviderController{
private Long id;
private String vat;
private String address;
private List<Product> products;
private Provider provider;
private List<Provider> providers;
public ProviderController() {
this.products= new LinkedList<>();
this.providers= new LinkedList<>();
}
//adds the Provider in the c:forEach of the view newProvider.jsp
public String addProvider() {
this.provider= new Provider(vat, address, products);
this.providers.add(this.provider);
return "newProvider";
}
-I omitted the facade because I have nothing to store in this case, I just want to add the provider in the list and THEN, with another method, add all the providers of the list in my db
-Provider is a Model that uses the annotation #Entity, so my doubt is that I can't use Provider if I don't use the EntityManager
If I'm right, what can I do to store simply in session my providers? I have to create another class Provider? I have to create another ProviderController?
Thank you very much for the answers.
Keeping apart from your hypothetical persistence layer, you can store the information in the session. However, you have to differ between the information that belongs to the session and the one that does to the current view.
For your case, I think you want to have the stored providers as a session variable, while the information you send in the form when adding a new one should be in view scope. That way you divide the logic of the application in a proper way. Here you've got more information about the view scope, introduced in JSF 2.
As you're already in JSF 2, you could choose between JSP and Facelets for your view technology. If it's a new project, I encourage you to go with facelets, as it is the standard for JSF 2:
ProviderController.java
/*
* Manages providers in the session
*/
#ManagedBean
#SessionScoped
public class ProviderController{
private List<Provider> providers;
private List<Product> products;
public ProviderController() {
this.products= new LinkedList<>();
this.providers= new LinkedList<>();
}
public List<Provider> getProviders(){
return providers;
}
}
providers.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head />
<h:body>
<!-- Display all the providers from the session -->
<ul>
<ui:repeat value="#{providerController.providers}" var="provider">
<li>#{provider.vat}-#{provider.address}</li>
</ui:repeat>
</ul>
</h:body>
</html>
ProviderAdd.java
/*
* Manages the view to add a new provider
*/
#ManagedBean
#ViewScoped
public class ProviderAdd{
private Long id;
private String vat;
private String address;
//Injects the session scoped bean
#ManagedProperty(value="#{providerController}")
private ProviderController providerController;
//Getter and setters
//Adds a new provider to the session and returns to the provider list
public String addProvider() {
this.provider= new Provider(this.vat, this.address, this.products);
providerController.getProviders.add(this.provider);
return "providers";
}
}
addProvider.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head />
<h:body>
<h2>VAT:</h2><h:inputText value="#{providerAdd.vat}" />
<h2>Address:</h2><h:inputText value="#{providerAdd.address}" />
<h:commandButton action="#{providerAdd.addProvider}" value="Add provider" />
</h:body>
</html>
Here's my FacesComponent class:
#FacesComponent("ExibicaoChecklistComponent")
public class ExibicaoChecklistComponent extends UINamingContainer {
private ListaChecklistWrapper checklist;
private String altura;
public ListaChecklistWrapper getChecklist() {
return checklist;
}
public void setChecklist(ListaChecklistWrapper checklist) {
this.checklist = checklist;
}
public String getAltura() {
return altura;
}
public void setAltura(String altura) {
this.altura = altura;
}
}
and the xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:pretty="http://ocpsoft.com/prettyfaces"
xmlns:ui="http://java.sun.com/jsf/facelets">
<cc:interface componentType="ExibicaoChecklistComponent">
<cc:attribute name="altura" default="300px" type="java.lang.String" />
<cc:attribute name="checklist" required="true" />
</cc:interface>
<cc:implementation>
Altura: #{cc.altura}
Checklist: #{cc.checklist.nome}
</cc:implementation>
and finally the usage:
<checando:exibicaoChecklist altura="200px" checklist="#{CheckBean.checklists[0]}" />
The setAltura method is called with the 200px value, but the setChecklist(ListaChecklistWrapper checklist) is not called and the checklist attribute is always null inside the component.
If I do #{CheckBean.checklists[0].nome} outside the <checando:exibi... tag it works. So, the object is not null... it's only a missing call to the set method.
Is there anything I'm missing?
Mojarra 2.1.13 (20120907-1514) and java version "1.7.0_25".
Thanks.
I guess, giving the nome directly as a parameter into the component does work again? (Something like setChecklistNome(String nome).
If so, there might be a challenge with giving direct parameters different from java.lang.String. Have you tried to give the parameters as cc.attrs.checklist instead from writing it directly into the UINamingContainer?
I'm developing a project using Spring #MVC (with MVC annotations).
If all request parameters shall be populated to a single bean everything seems fine, but what about multiple POJOs?
I have searched the web and am aware of form-backing-objects, but how can I use them in #MVC (annotation-based)?
Another question: shall I construct a bean for each form? Doesn't it just look like Strut's ActionForms? Is there anyway to prevent creating these objects?
Is there a way, to put all beans in a Map and ask Spring binder to populate them? Something like:
map.put("department", new Department());
map.put("person", new Person());
so department.name and department.id bind into department bean, and person.name, person.sex and ... populate in the person bean? (So the controller method accepts a Map as its parameter).
Form backing objects are not mandatory, you can use #RequestParam annotation to obtain the form values directly. See Binding request parameters to method parameters with #RequestParam on Spring Manual.
I don't think Map is a supported by the default Spring MVC type converters, but you can register a custom converter. See Customizing WebDataBinder initialization.
If you give Person a reference of Department then it will be easy. In your app, if the person works in a department it will be logical to create a Has-A relationship in your Person class like this:
#Component
#Scope("prototype")
public class Person {
private String firstName;
private Department department;
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
You can create a Controller that gets a Person bean from the Context and renders a view.
#Controller
public class TestController implements ApplicationContextAware{
private ApplicationContext appContext;
#RequestMapping(value="/handleGet",method=RequestMethod.GET)
public String handleGet(ModelMap map){
map.addAttribute("person", appContext.getBean("person"));
return "test";
}
#RequestMapping(value="/handlePost",method=RequestMethod.POST)
public #ResponseBody String handlePost(#ModelAttribute("person") Person person){
return person.getDepartment().getDepartmentName();
}
#Override
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
this.appContext=appContext;
}
}
Then inside your JSP view you can write something like this:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Test</title>
</head>
<body>
<sf:form commandName="person" action="/appname/handlePost.html" method="post">
<sf:input path="firstName"/>
<sf:input path="department.departmentName"/>
<sf:button name="Submit">Submit</sf:button>
</sf:form>
</body>
</html>
I am newbie in JSF 2.0, I worked in JSF 1.1 and 1.2 and I populate selectOneMenu in constructor of Managed bean's page. For when users to acces to page the List is populate. example below. I put the same in JSF 2.0 but is not work, the selectOneMenu appears empty.
<h:selectOneMenu id="cboStatus" value="#{PersonBean.idStatus}">
<f:selectItems value="#{PersonBean.status}"/>
</h:selectOneMenu>
In constructor's managed bean I put:
public class PersonBean {
private SelectItem[] status=new SelectItem[0];
public PersonBean () {
detallePersonas= new ArrayList();
status= new SelectItem[3];
status[0]=new SelectItem("S","Single");
status[1]=new SelectItem("M","Married");
status[2]=new SelectItem("D","Divorced");
}
}
Editor Netbeans 6.8 (JSF 2.0 default configuration wizard)
No Exception Error
Never run the constructor PersonBean (I put a breakpoint and never stops)
There are other ways to populate selects to load the page
This is the complete code:
index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Person</title>
</h:head>
<h:body>
<h:form id="frmPerson">
<h:outputLabel id="lblStatus" value="Status:"/>
<h:selectOneMenu id="cboStatus" value="#{PersonBean.idStatus}">
<f:selectItems value="#{PersonBean.status}"/>
</h:selectOneMenu>
</h:form>
</h:body>
</html>
PersonBean.java
package com.prueba.backingbean;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;
/**
*
* #author Administrador
*/
#ManagedBean(name = "Person")
#ViewScoped
public class PersonBean {
private String idStatus;
private SelectItem[] status = new SelectItem[0];
public PersonBean() {
status = new SelectItem[3];
status[0] = new SelectItem("S", "Single");
status[1] = new SelectItem("M", "Married");
status[2] = new SelectItem("D", "Divorced");
}
/**
* #return the idStatus
*/
public String getIdStatus() {
return idStatus;
}
/**
* #param idStatus the idStatus to set
*/
public void setIdStatus(String idStatus) {
this.idStatus = idStatus;
}
/**
* #return the status
*/
public SelectItem[] getStatus() {
return status;
}
/**
* #param status the status to set
*/
public void setStatus(SelectItem[] status) {
this.status = status;
}
}
private Map<String,String>status = new HashMap<String,String>();
.......
status.put("S", "Single");
status.put("M", "Married");
status.put("D", "Divorced");
in JSF PAGE:
<h:selectOneMenu value="#{personBean.idStatus}" >
<f:selectItems value="#{personBean.status}"/>
</h:selectOneMenu>
It should be "personBean" instead of "PersonBean" (first letter should be lowercase). You also need getter for status (getStatus()) and setter/getter for idStatus (setIdStatus()/getIdStatus()). Are they there?
Look here:
#ManagedBean(name = "Person")
#ViewScoped
public class PersonBean {
You've declared the managed bean name as Person. So it's in JSF EL available as #{Person}. Yet you're attempting to access it as #{PersonBean}. Because such a bean does not exist, the menu remains empty.
You've 3 options:
Rename #{PersonBean} by #{Person} in your JSF page.
Rename #ManagedBean(name = "Person") to #ManagedBean(name = "PersonBean") in your managed bean.
Get rid of bean name and use the default JSF naming conventions. I.e. just use #ManagedBean without a name and use #{personBean} in your JSF page (in essence, the bean's class name with first character lowercased).
Option 3 is preferred.
Have you tried using List instead of Array of SelectItems.
Below code might help you.
private List<SelectItem> status = new ArrayList<SelectItem>();
status.add(new SelectItem("S","Single"));
status.add(new SelectItem("M","Married"));
status.add(new SelectItem("D","Divorced"));
/*
SETTER / GETTER
*/
I generated a new form using sean-gen (seam new-form) and added another field to it using an #In annotation:
#Stateful
#Name("dummy")
public class DummyBean implements Dummy
{
#Logger private Log log;
#In StatusMessages statusMessages;
#In private String bar;
private String foo;
public void doStuff()
{
String msg = "dummy.doStuff() action called with foo: #{dummy.foo} and bar: #{bar}. instance variable for bar:" + bar;
log.info(msg);
statusMessages.add(msg);
}
#Length(max = 10)
public String getFoo()
{
return foo;
}
public void setFoo(String value)
{
this.foo = value;
}
#Remove
public void destroy() {}
}
The interface is this one:
#Local
public interface Dummy
{
public void doStuff();
public String getFoo();
public void setFoo(String value);
public void destroy();
}
The problem is, when I try to access the properties I get:
javax.faces.FacesException: javax.el.ELException: /dummy.xhtml #22,52 value="#{dummy.foo}": Error reading 'foo' on type org.javassist.tmp.java.lang.Object_$$_javassist_seam_2
at javax.faces.component.UIOutput.getValue(UIOutput.java:187)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:201)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:284)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:154)
.
.
.
Caused by: javax.ejb.EJBTransactionRolledbackException: #In attribute requires non-null value: dummy.bar
at org.jboss.ejb3.tx.Ejb3TxPolicy.handleInCallerTx(Ejb3TxPolicy.java:115)
at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:130)
My view is this:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:a="http://richfaces.org/a4j"
template="layout/template.xhtml">
<ui:define name="body">
<h:form id="dummyForm">
<rich:panel>
<f:facet name="header">dummy header</f:facet>
<s:decorate id="fooField" template="layout/edit.xhtml">
<ui:define name="label">Foo</ui:define>
<h:inputText id="foo" required="true"
value="#{dummy.foo}"/>
</s:decorate>
<s:decorate id="barField" template="layout/edit.xhtml">
<ui:define name="label">Bar</ui:define>
<h:inputText id="bar" required="true"
value="#{bar}"/>
</s:decorate>
<div style="clear:both"/>
</rich:panel>
<div class="actionButtons">
<h:commandButton id="doStuff" value="doStuff"
action="#{dummy.doStuff}"/>
</div>
</h:form>
</ui:define>
</ui:composition>
If I remove either 'fooField' or 'barField' the view renders and works correctly, but if I try to use both at the same time I get the above exception.
I also noticed that if I use only #In annotations (remove the accessor methods from the bean) the page works.
Is this something expected and I should be doing my homework before asking?
I'm using JBoss 5.1.0.GA, Seam 2.2.0.GA and Java 6.
Turns out this is expected behavior, quoting an answer from the seam forum:
Use #In(required=false) if the Seam component you're injecting does not have the #AutoCreate annotation at the class level.
So, changing:
#In private String bar;
to:
#In (required=false) private String bar;
fixes the issue.