I've got a simple composite component which has to render a inputText. When a put the value and press commandButton the follow exception is throw:
java.lang.IllegalArgumentException: Cannot convert 1 of type class java.lang.String to class sample.entity.Product
When i use h:inputText instead d:myInputText it's work fine.
Is possible use a FacesConverter and attribute forClass for composite component? I do not like to use converter attribute or converterId of tag f:converter.
Anybody help me?
Page code:
<h:form>
<h:messages />
Product Id: <h:myInputText value="#{productController.product}"/>
<h:commandButton value="Submit" action="#{productController.someAction()}" />
Product Description: <h:outputText value="#{productController.product.description}"/>
</h:form>
Composite code:
<composite:interface>
<composite:attribute name="value"/>
<composite:editableValueHolder name="value" targets="#{cc.clientId}:value"/>
</composite:interface>
<composite:implementation>
<div id="#{cc.clientId}">
<h:inputText id="value" value="#{cc.attrs.value}"/>
<h:message for="#{cc.clientId}:value" />
</div>
</composite:implementation>
ManagedBean code:
#Named("productController")
#RequestScoped
public class ProductController {
private Product product;
public Product getProduct() {
if (product == null) {
product = new Product();
}
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public void someAction() {
System.out.println("Product " + product);
}
}
Converter code:
#FacesConverter(forClass = Product.class)
public class ProductConverter implements Converter {
#Override
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
System.out.println("[DEBUG] getAsObject: " + value);
if (value == null || "".equals(value)) {
return null;
}
//TODO: some logic to get entity from database.
return new Product(new Long(value));
}
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object o) {
System.out.println("[DEBUG] getAsString: " + o);
if (o == null) {
return null;
}
return String.valueOf(((Product) o).getId());
}
}
Entity code:
public class Product {
private Long id;
private String description;
public Product() {
}
public Product(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public int hashCode() {
int hash = 7;
hash = 29 * hash + (this.id != null ? this.id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Product other = (Product) obj;
if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Product{" + "id=" + id + '}';
}
}
I use Mojarra 2.1.14, Glassfish 3.1 and CDI.
Best regards.
I was able to reproduce it in Mojarra 2.1.14. This is a bug in Mojarra. It works fine in MyFaces 2.1.9. I've reported it to Mojarra guys as issue 2568. In the meanwhile, there's not really another option than explicitly specifying a <f:converter for> in the client or moving to MyFaces (which has its own set of specific quirks/issues as well though).
Related
I wanted to create my own date converter.I have input field with f:converter id="MyConverter". When I type "today" value I want show today date. Method getAsObject is working good. I've got value "today" from input field and return new LocalDate(), but method getAsObject() have always null as a value. What should I do to fix it?
#FacesConverter(forClass = Date.class, value = "MyConverter")
public class MyConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
if (value == null) {
return null;
}
if (value.equals("today")) {
return new LocalDate();
}
//do something else
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException {
// value is always null!
if (value instanceof LocalDate) {
LocalDate date = (LocalDate) value;
return date.toString();
} else {
return "";
}
}
EDIT:
jsf tag (it is a little bit complicated) it's actually 2 date input fields (Date interval component), and I want to use MyDateConverter on it:
<cc:interface componentType="DateIntervalComponent">
<cc:attribute name="value" required="true" />
<cc:attribute name="placeholder" />
<cc:attribute name="labelFromDate" default="From Date" />
<cc:attribute name="labelToDate" default="To Date" />
</cc:interface>
<cc:implementation>
<div id="#{cc.userId}">
<b:input id="fromDate" binding="#{cc.FromDateComponent}"
label="#{cc.attrs.labelFromDate}">
<f:converter converterId="MyConverter" />
<f:ajax render="#{cc.userId}" />
</b:input>
<b:input id="toDate" binding="#{cc.ToDateComponent}"
label="#{cc.attrs.labelToDate}">
<f:converter converterId="MyConverter" />
<f:ajax render="#{cc.userId}" />
</b:input>
</div>
</cc:implementation>
#FacesComponent("DateIntervalComponent")
public class DateIntervalComponent extends UIInput implements NamingContainer {
private UIInput fromDateComponent;
private UIInput toDateComponent;
public DateIntervalComponent() {
setRendererType(null);
}
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
#Override
public DateInterval getValue() {
return (DateInterval) super.getValue();
}
#Override
public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
super.processEvent(event);
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
if (fromDateComponent != null && toDateComponent != null) {
DateInterval value = getValue();
if (!fromDateComponent.isLocalValueSet()) {
fromDateComponent.setValue(value != null ? value.getStart() : null);
}
if (!toDateComponent.isLocalValueSet()) {
toDateComponent.setValue(value != null ? value.getEnd() : null);
}
}
super.encodeBegin(context);
}
#Override
public DateInterval getSubmittedValue() {
Object startValue = fromDateComponent.getValue();
Object endValue = toDateComponent.getValue();
return new DateInterval((Date) startValue, (Date) endValue);
}
#Override
public void validate(FacesContext context) {
super.validate(context);
if (!isValid()) {
fromDateComponent.setValid(false);
toDateComponent.setValid(false);
return;
}
}
#Override
public void resetValue() {
super.resetValue();
fromDateComponent.resetValue();
toDateComponent.resetValue();
}
public UIInput getFromDateComponent() {
return fromDateComponent;
}
public UIInput getToDateComponent() {
return toDateComponent;
}
public void setToDateComponent(UIInput toDateComponent) {
this.toDateComponent = toDateComponent;
}
public void setFromDateComponent(UIInput fromDateComponent) {
this.fromDateComponent = fromDateComponent;
}
}
regards
You need to keep track of the state of your attributes as soon as the FacesComponent itself is STATELESS.
I use the following strategy to keep state of FacesComponent attibutes
First of all, create a generic class based on UINamingContainer (if this is your type of component).
public class MyUINamingContainer extends UINamingContainer {
#SuppressWarnings("unchecked")
/**
* Searches for an attribute and return it.
*/
protected <T> T getAttribute(String attName) {
return (T) getStateHelper().eval(attName);
}
#SuppressWarnings("unchecked")
/**
* Evaluate an attribute and return it if found.
*/
protected <T> T getAttribute(String localName, String attName) {
return (T) getStateHelper().eval(localName, getAttributes().get(attName));
}
/**
* Refresh the attributes state
*
* #param <T>
* #param attName attribute's name. This name will identify the attribute into the map.
It must be different from the name used to the attribute on the view, otherwise
it will cause a infinite loop.
* #param value attribute's value.
*/
protected <T> void setAttribute(String attName, T value) {
getStateHelper().put(attName, value);
}
}
Then, make my FacesComponent class inherit from it, so it would know the stateful getters and setters:
#FacesComponent("myComponent")
public class MyComponent extends MyUINamingContainer {
public SomeType getMyAttributeOnStateMap() {
return getAttribute("myAttributeOnStateMap","myAttribute");
}
public void setMyAttributeOnStateMap(SomeType myAttribute) {
setAttribute("myAttributeOnStateMap", myAttribute);
}
}
Into the component xhtml code:
<cc:interface componentType="myComponent">
<cc:attribute name="myAttribute"/>
</cc:interface>
<cc:implementation>
<h:input value="#{cc.myAttributeOnStateMap}" />
<cc:implementation>
PS.: Note that the attribute has a different name into the map. This is because it will get stuck in a loop it you use the same name for the map attribute and the view one. The method getAttribute(String,String) would always look for the same attribute and never find anything, leading you to a overflow.
PS2.: Note that the name used as the value into the h:input was the name used to store it into the map.
I'm kinda new to JSF and primefaces and I'm running into a very annoying problem.
I'm making a very basic application to learn a bit more about primefaces. I have a simple form that has several textual input fields, two datepickers and one dropdown (selectOneMenu).
Everything works all values are put in the backing bean when I submit the form, except for the value from the dropdown menu. The setter for that item is never called. And the application does not call the public void saveNewActivity(ActionEvent evt) method on the controller as defined on the commandbutton. When I however remove or comment out the dropdown menu in html it does call that method (but the field for the dropdown menu is obviously null).
I've been trying things for nearly two days, and still can't get this to work properly.
I have the following code (snippets):
My html/jsf code
<div id="newActivitycontent">
<h:form id="newActivityForm">
<h:messages id="messages"/>
<table>
<tr>
<td>Gebruiker:</td>
<td><p:selectOneMenu value="#{plannedActivityController.newActivity.organiser}}"
converter="#{userConverter}">
<f:selectItem itemLabel="Kies een gebruiker" itemValue=""/>
<f:selectItems value="#{plannedActivityController.users}" var="user"
itemLabel="#{user.firstname} #{user.lastname}" itemValue="#{user}"/>
</p:selectOneMenu></td>
</tr>
<tr>
<td>Titel:</td>
<td><p:inputText value="#{plannedActivityController.newActivity.name}"/></td>
</tr>
<tr>
<td>Beschrijving:</td>
<td><p:inputText value="#{plannedActivityController.newActivity.desctription}"/></td>
</tr>
<tr>
<td>Startdatum:</td>
<td><p:calendar value="#{plannedActivityController.newActivity.startDateDate}"/></td>
</tr>
<tr>
<td>Einddatum:</td>
<td><p:calendar value="#{plannedActivityController.newActivity.endDateDate}"/></td>
</tr>
</table>
<p:commandButton id="btnSaveNewActivity" value="Opslaan"
actionListener="#{plannedActivityController.saveNewActivity}"
update=":overviewForm:activityTable messages"/>
<p:commandButton id="btnCancelNewActivity" value="Annuleren"
actionListener="#{plannedActivityController.cancelNewActivity}" onclick="hideAddNewUI()"
update=":overviewForm:activityTable" type="reset" immediate="true"/>
</h:form>
</div>
The controller that is used by that code:
#Named
#SessionScoped
public class PlannedActivityController implements Serializable {
#Inject
private ApplicationModel appModel;
#Inject
private SessionModel sessionModel;
#Inject
private ActivityMapper activityMapper;
#Inject
private UserMapper userMapper;
private ActivityBean newActivity;
private ActivityBean selectedActivity;
private List<ActivityBean> activities;
private List<UserBean> users;
public PlannedActivityController() {
}
#PostConstruct
public void onCreated() {
convertActivities();
onNewActivity();
users = userMapper.mapToValueObjects(appModel.getUsers());
}
public void convertActivities() {
List<PlannedActivity> originalActivities = appModel.getActivities();
this.activities = activityMapper.mapToValueObjects(originalActivities);
}
public void onRowEditComplete(RowEditEvent event) {
System.out.println("row edited : " + event.getObject());
//TODO: save changes back to db!
}
public void onRowSelectionMade(SelectEvent event) {
System.out.println("row selected : " + event.getObject());
selectedActivity = (ActivityBean)event.getObject();
}
//Activity crud methods
public void onNewActivity() {
newActivity = new ActivityBean();
newActivity.setId(new Date().getTime());
}
public void saveNewActivity(ActionEvent evt) {
PlannedActivity newAct = activityMapper.mapToEntity(newActivity);
if(newAct != null) {
appModel.getActivities().add(newAct);
}
convertActivities();
}
public void cancelNewActivity() {
//TODO: cleanup.
}
public void deleteSelectedActivity() {
if(selectedActivity != null) {
activities.remove(selectedActivity);
appModel.setActivities(activityMapper.mapToEntities(activities));
convertActivities();
} else {
//TODO: show error or information dialog, that delete cannot be done when nothing has been selected!
}
}
//Getters & Setters
public ApplicationModel getAppModel() {
return appModel;
}
public void setAppModel(ApplicationModel appModel) {
this.appModel = appModel;
}
public SessionModel getSessionModel() {
return sessionModel;
}
public void setSessionModel(SessionModel sessionModel) {
this.sessionModel = sessionModel;
}
public ActivityMapper getActivityMapper() {
return activityMapper;
}
public void setActivityMapper(ActivityMapper activityMapper) {
this.activityMapper = activityMapper;
}
public UserMapper getUserMapper() {
return userMapper;
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
public ActivityBean getNewActivity() {
return newActivity;
}
public void setNewActivity(ActivityBean newActivity) {
this.newActivity = newActivity;
}
public ActivityBean getSelectedActivity() {
return selectedActivity;
}
public void setSelectedActivity(ActivityBean selectedActivity) {
this.selectedActivity = selectedActivity;
}
public List<ActivityBean> getActivities() {
return activities;
}
public void setActivities(List<ActivityBean> activities) {
this.activities = activities;
}
public List<UserBean> getUsers() {
return users;
}
public void setUsers(List<UserBean> users) {
this.users = users;
}
}
My activitybean:
public class ActivityBean implements Serializable {
private Long id = 0L;
private String name;
private String desctription;
private UserBean organiser;
private Calendar startDate;
private Calendar endDate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesctription() {
return desctription;
}
public void setDesctription(String desctription) {
this.desctription = desctription;
}
public UserBean getOrganiser() {
return organiser;
}
public void setOrganiser(UserBean organiser) {
this.organiser = organiser;
}
public Calendar getStartDate() {
return startDate;
}
public void setStartDate(Calendar startDate) {
this.startDate = startDate;
}
public Date getStartDateDate() {
if(this.startDate == null) {
return null;
}
return this.endDate.getTime();
}
public void setStartDateDate(Date startDate) {
if(this.startDate == null) {
this.startDate = new GregorianCalendar();
}
this.startDate.setTime(startDate);
}
public String getStartDateString() {
if(this.startDate == null) {
return null;
}
return startDate.get(Calendar.DAY_OF_MONTH) + "/" + startDate.get(Calendar.MONTH) + "/" + startDate.get(Calendar.YEAR) + "";
}
public Calendar getEndDate() {
return endDate;
}
public void setEndDate(Calendar endDate) {
this.endDate = endDate;
}
public Date getEndDateDate() {
if(this.endDate == null) {
return null;
}
return endDate.getTime();
}
public void setEndDateDate(Date endDate) {
if(this.endDate == null) {
this.endDate = new GregorianCalendar();
}
this.endDate.setTime(endDate);
}
public String getEndDateString() {
if(this.endDate == null) {
return null;
}
return endDate.get(Calendar.DAY_OF_MONTH) + "/" + endDate.get(Calendar.MONTH) + "/" + endDate.get(Calendar.YEAR) + "";
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ActivityBean that = (ActivityBean) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return true;
}
#Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
My userbean:
public class UserBean {
private Long id;
private String username;
private String firstname;
private String lastname;
private String email;
private String phone;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserBean userBean = (UserBean) o;
if (id != null ? !id.equals(userBean.id) : userBean.id != null) return false;
return true;
}
#Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
And the converter used by the selectOneMenu:
#Named
public class userConverter implements Converter{
#Inject
private PlannedActivityController activityController;
#Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
for (UserBean user : activityController.getUsers()) {
if(user.getId().toString().equals(s)) {
return user;
}
}
return null;
}
#Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {
if(o instanceof UserBean) {
UserBean user = (UserBean)o;
return user.getId().toString();
}
return "";
}
}
The problem is here. Look closer. This is invalid EL syntax.
value="#{plannedActivityController.newActivity.organiser}}"
This should however have thrown a PropertyNotWritableException on submit something like this:
javax.el.PropertyNotWritableException: /test.xhtml #25,39 value="#{plannedActivityController.newActivity.organiser}}": Illegal Syntax for Set Operation
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:136)
at javax.faces.component.UIInput.updateModel(UIInput.java:822)
at javax.faces.component.UIInput.processUpdates(UIInput.java:739)
at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1244)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1244)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1223)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
This exception should have been logged to the server log. By default this will however not end up in an error page for the enduser because JSF/PrimeFaces have by default no form of feedback to enduser in case of exceptions which are thrown during ajax requests. You should however be able to see it in actual ajax response body in webbrowser's builtin HTTP traffic monitor.
The JSF utility library OmniFaces offers a FullAjaxExceptionHandler for the very problem of total absence of feedback on exceptions during ajax requests. You may find it useful. When I tried to recreate your problem, I was been presented a clear error page so that I don't need to dig in server log or HTTP traffic monitor for clues.
I have a list of governorates that I displayed in a <p:selectOneMenu>
the java code in the managed bean:
public List<SelectItem> gouvernorats() {
List<Gouvernorat> all = emetteursEJB.findAllGouvernorat();
List<SelectItem> items = new ArrayList<>();
for (Gouvernorat g : all) {
items.add(new SelectItem(g, g.getLibelleGouv()));
}
return items;
}
in the <p:selectOneMenu> I add <p:ajax>:
<p:selectOneMenu value="#{emetteurBean.selectedGouvernorat}" style="width:160px" >
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{emetteurBean.gouvernorats()}" />
<p:ajax event="change" listener="#{emetteursBean.handelGouvChanged()"/>
</p:selectOneMenu>
in the method handelGouvChanged() selectedGouvernorat object is always null;
Recently I added the convert I stumbled upon NullPointerException
#FacesConverter(forClass = Gouvernorat.class)
public class EmetteursConverter implements Converter {
#EJB
private ReferentielDaoLocal refEJB;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String selectedValue) {
System.out.println("Inside The Converter");
System.out.println(selectedValue.length());
if (selectedValue == null) {
return null;
} else {
return refEJB.findGouvByCode(selectedValue.trim());
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return null;
} else {
return String.valueOf(((Gouvernorat) value).getIdGouvernorat());
}
}
}
I found a solution, I injected EJB with InitilContext.lookup ()
#FacesConverter(forClass = Gouvernorat.class)
public class GouvernoratConverter implements Converter {
private static final Logger LOG = Logger.getLogger(GouvernoratConverter.class.getName());
#Override
public Object getAsObject(FacesContext context, UIComponent component, String selectedValue) {
if (selectedValue == null) {
return null;
} else {
try {
ReferentielDaoLocal myService = (ReferentielDaoLocal) new
InitialContext().lookup("java:global/ErpCCF/ErpCCF-ejb/ReferentielDaoImpl");
return myService.findGouvByCode(selectedValue);
} catch (NamingException ex) {
LOG.log(Level.SEVERE, "Converter Gouvernorat Error", ex.getMessage());
return null;
}
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return null;
} else {
return String.valueOf(((Gouvernorat) value).getIdGouvernorat());
}
}
}
I filled my rightList of the PickList with Objects from a web service, but when i select some elements, i want to get these elements in myManagedBean, because i'll affect them to an Object.
JSF :
<h:form>
<rich:panel>
<h:panelGrid columns="2" styleClass="criteresSaisie"
rowClasses="critereLigne" columnClasses="titreColonne,">
<h:outputLabel for="libelleCoplement" value=" "
size="20" />
<rich:pickList d="libelleCoplement" sourceCaption="Compléments"
targetCaption="Compléments sélectionnés"
value="#{listeCmpltDispoModel.listeCmpltSelect}" size="15"
addText=">" addAllText=">>" removeText="<"
removeAllText="<<" listWidth="270px" listHeight="110px"
orderable="true">
<f:converter converterId="cmpltsTitresConcerter" />
<f:selectItems value="#{listeCmpltDispoModel.listeCmpltDispo}"
var="liste" itemLabel="#{liste.libelleComplement}"
itemValue="#{liste.cdComplement}"/>
</rich:pickList>
</h:panelGrid>
<h:panelGroup>
<div align="right">
<h:panelGrid columns="8">
<h:commandButton value="Valider"
action="#{saisieCmpltsTitreCtrl.valider}" />
</h:panelGrid>
</div>
</h:panelGroup>
</rich:panel>
</h:form>
The bean :
#ManagedBean(name = "listeCmpltDispoModel")
#SessionScoped
public class ListeCmpltDispoModel implements Serializable {
private static final long serialVersionUID = 1L;
private Long cdComplement;
private String libelleComplement;
private int nbCompl;
private List<ComplementsDispoSortieDTO> listeCmpltDispo ;
private List<ComplementsDispoSortieDTO> listeCmpltSelect ;
public ListeCmpltDispoModel() {
}
public Long getCodeComplement() {
return cdComplement;
}
public void setCodeComplement(Long cdComplement) {
this.cdComplement = cdComplement;
}
public String getLibelleComplement1() {
return libelleComplement;
}
public void setLibelleComplement1(String libelleCoplement) {
this.libelleComplement = libelleCoplement;
}
public Long getCdComplement() {
return cdComplement;
}
public void setCdComplement(Long cdComplement) {
this.cdComplement = cdComplement;
}
public String getLibelleComplement() {
return libelleComplement;
}
public void setLibelleComplement(String libelleComplement) {
this.libelleComplement = libelleComplement;
}
public List<ComplementsDispoSortieDTO> getListeCmpltDispo() {
return listeCmpltDispo;
}
public void setListeCmpltDispo(List<ComplementsDispoSortieDTO> listeCmpltDispo) {
this.listeCmpltDispo = listeCmpltDispo;
}
public int getNbCompl() {
return nbCompl;
}
public void setNbCompl(int nbCompl) {
this.nbCompl = nbCompl;
}
public List<ComplementsDispoSortieDTO> getListeCmpltSelect() {
return listeCmpltSelect;
}
public void setListeCmpltSelect(List<ComplementsDispoSortieDTO> listeCmpltSelect) {
this.listeCmpltSelect = listeCmpltSelect;
}
}
Converter :
#FacesConverter(value="cmpltsTitresConcerter")
public class CmpltsTitresConcerter implements Converter {
#SuppressWarnings("null")
public Object getAsObject(FacesContext context, UIComponent component,
String value){
ComplementsDispoSortieDTO cmpltSelect = null;
cmpltSelect.setCdComplement(Long.parseLong(value));
return cmpltSelect;
}
public String getAsString(FacesContext arg0, UIComponent arg1, Object obj) {
return String.valueOf(((ComplementsDispoSortieDTO) obj).getCdComplement());
}
}
Any help is greatly apprectiated!
Roughtly you need 3 things :
Custom converter for your object (Object to String, String to Object)
Getter/Setter with the List of your Objects choices
Getter/Setter with the List of your Objects selected
Everything is perfectly described here : RichFaces Showcase - pickList
EDIT :
Adding this should fix your problem :
<rich:pickList ...>
<f:converter converterId="cmpltsTitresConcerter" />
</rich:pickList>
also the converter property in <f:selectItems /> is not valid : f:selectItems
EDIT :
You should modify your converter like that to remove converting exceptions :
#FacesConverter(value="cmpltsTitresConcerter")
public class CmpltsTitresConcerter implements Converter
{
public Object getAsObject(FacesContext context, UIComponent component, String value)
{
ComplementsDispoSortieDTO cmpltSelect = null;
if(value != null)
{
cmpltSelect = new ComplementsDispoSortieDTO();
cmpltSelect.setCdComplement(Long.parseLong(value));
}
return cmpltSelect;
}
public String getAsString(FacesContext arg0, UIComponent arg1, Object obj)
{
String result = null;
if(obj != null)
{
result = String.valueOf(((ComplementsDispoSortieDTO) obj).getCdComplement());
}
return result;
}
}
Your selected objects are bound to the value attribute which must have a getter and setter.
I am surprised that underscore ("_") is not working in OGNL.
In below sample all properties are processed on OGNL/ValueStack, except property name appfull_name due to underscore.
Code sample below
POJO SampleSdmAppsTabObj.java
import java.io.*;
import javax.persistence.*;
#SuppressWarnings("serial")
#Entity
#Table(name="SDM_APPS")
#IdClass(SdmAppsPkeyObj.class)
public class SdmAppsTabObj implements Serializable
{
//#Id
String orgid;
//#Id
String asnid;
String appfull_name;
String description;
public SdmAppsTabObj(){}
public SdmAppsTabObj
(
String inOrgId,
String inAsnId,
String inAppFullName,
String inDescription
)
{
this.OrgId = inOrgId;
this.AsnId = inAsnId;
this.AppFullName = inAppFullName;
this.Description = inDescription;
}
*/
public String getOrgid() { return orgid; }
public String getAsnid() { return asnid; }
public String getAppfullname() { return appfull_name; }
public String getDescription() { return description; }
public void setOrgid(String inOrgId ) { this.orgid = inOrgId; }
public void setAsnid(String inAsnId ) { this.asnid = inAsnId; }
public void setAppfullname(String inAppFullName ) { this.appfull_name = inAppFullName; }
public void setDescription(String inDescription ) { this.description = inDescription; }
//Override equals() and hashCode()
#Override
public boolean equals(Object inObject)
{
if (this == inObject) { return true; }
if (inObject == null) { return false; }
if (!(inObject instanceof SdmAppsTabObj)) { return false; }
SdmAppsTabObj other = (SdmAppsTabObj) inObject;
if( orgid == null )
if( other.orgid != null ) { return false; }
else if( !orgid.equals(other.orgid) ) { return false; }
if( asnid == null )
if( other.asnid != null ) { return false; }
else if( !asnid.equals(other.asnid) ) { return false; }
return true;
}
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((orgid == null) ? 0 : orgid.hashCode());
result = prime * result + ((asnid == null) ? 0 : asnid.hashCode());
return result;
}
}
SdmAppsAction.java
import SdmAppsTabObj;
import SdmAppsPkeyObj;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class SdmAppsAction extends ActionSupport implements ModelDriven<SdmAppsTabObj>{
private static final long serialVersionUID = 1L;
SdmAppsTabObj lSdmAppsTabObj = new SdmAppsTabObj();
public String execute() throws Exception {
return SUCCESS;
}
public SdmAppsTabObj getModel() {
return lSdmAppsTabObj;
}
}
sdm_apps_add.jsp
.....
<h2>Add Apps</h2>
<s:form action="sdmAppsAction" >
<s:textfield name="orgid" label="Org" />
<s:textfield name="asnid" label="Asn" value=""/>
<s:textfield name="appfull_name" label="App name" value=""/>
<s:textfield name="description" label="Desc" value=""/>
<s:submit />
</s:form>
.....
sdm_apps_success.jsp
.....
<h2>Apps Details</h2>
Org : <s:property value="orgid" /><br>
Asn : <s:property value="asnid" /><br>
App name : <s:property value="appfull_name" /><br>
Desc : <s:property value="description" /><br>
.....
The getter of your appfull_name is
public String getAppfullname();
instead of:
public String getAppfull_name();
Also, the name of setter is not correct.