picklist PrimeFaces - How to get data from target-list? - jsf

I've created a picklist via PrimeFaces. Now i want to handle the selected items which are listed in the target list when i click the commandButton.
I want to pass the data through the controller and store them in my database. But everytime i call the function duallist.getTarget() it's empty.
I've crated a foreach-Loop where i want to select all items in the target list:
Controller (Bean):
private List<DTOAktivitaet> source = new ArrayList<DTOAktivitaet>();
private List<DTOAktivitaet> target = new ArrayList<DTOAktivitaet>();
private List<DTOAktivitaet> zwischen = new ArrayList<DTOAktivitaet>();
public void speicherAktiZug() {
DTOAktivitaet aktivitaet_vorgaenger = null;
for (DTOAktivitaet item : controller.getAktivitaeten()) {
if (item.toString().equals(selected)) {
aktivitaet_vorgaenger = item;
}
}
for (DTOAktivitaet aktivitaet : zwischen) {
try {
dao.aktiZugAkt(aktivitaet_vorgaenger, aktivitaet);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public AktiListController() {
for (DTOAktivitaet ak : controller.getAktivitaeten()) {
source.add(ak);
}
aktis = new DualListModel<DTOAktivitaet>(source, target);
zwischen = aktis.getTarget();
}
JSF:
<h:form id="form" name="formular">
<h:outputText id="aktivitaet"
value="#{aktiListController.selected}" />
<p:pickList id="pickList" value="#{aktiListController.aktis}"
var="aktivitaet" itemValue="#{aktivitaet}"
itemLabel="#{aktivitaet}" converter="aktivitaetsConverter"
showSourceControls="true" showTargetControls="true" />
<h:commandButton
action="#{aktiListController.speicherAktiZug}"
value="Aktivität-Abhängigkeit anlegen" class="commandButton">
</h:commandButton>
</h:form>
Converter:
#EJB
public class AktiListConverter implements Converter {
private InitialisierungController controller = InitialisierungController
.getInstance();
DTOAktivitaet aktivitaet = new DTOAktivitaet();
String name = "";
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
for (DTOAktivitaet item : controller.getAktivitaeten()) {
if (item.toString().equalsIgnoreCase(arg2)) {
this.aktivitaet = item;
System.out.println(aktivitaet);
return aktivitaet;
}
}
return null;
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
this.aktivitaet = (DTOAktivitaet) arg2;
return this.name = aktivitaet.getTeambezeichnung();
}
}
My Problem: The target-List is empty before i want to store the items in my database.

I don't fully understand your code as it is not written in English but as far as I can see your Converter is written badly. As far as I can see you do a toString() and a fromString() basically. This is quite error prone and the way you did it, heavy in performance. It is a better idea to use unique ID's (business or database).
Example:
#FacesConverter(value = "aktiListConverter")
public class AktiListConverter implements Converter
{
private InitialisierungController controller = InitialisierungController.getInstance();
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2)
{
//Get object by it's unique ID
return controller.getById(Long.parseLong(arg2));
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2)
{
//Return object's unique ID
return ((DTOAktivitaet) arg2).getId();
}
}
In stead of using the object as itemLabel (which performs a toString()) use something that generates a nice label like getName() for a person.
itemLabel="#{aktivitaet.nameOrSomething}"
The speicherAktiZug() method doesn't really make sense to me so I came this far:
public class AktiListController
{
private List<DTOAktivitaet> source;
private List<DTOAktivitaet> target = new ArrayList<DTOAktivitaet>();
private DualListModel<DTOAktivitaet> aktis;
public AktiListController()
{
source = controller.getAktivitaeten();
aktis = new DualListModel<DTOAktivitaet>(source, target);
}
//Getters and setters
public void speicherAktiZug()
{
target = aktis.getTarget();
//target should contain the picked items here.
}
}
I see you are also using aktiListController.selected but I cannot see what it's used for.

Names of Conterter between (XHTML) and (Class Converter) is not equal.
converter="aktivitaetsConverter"
public class AktiListConverter implements Converter {...}

Related

Primefaces OrderList and Converter: getAsObject() called with "[object Object]" String

This can be seen as a continuation of my other question.
In my backend view, I have a list of some POJO. The POJO is converted to JSON with its toString() method:
BackingView.java
#Getter #Setter private List<SomePOJO> pojoList = ...
SomePojo.java
#EqualsAndHashCode(callSuper = false, of = {"id"})
public class SomePOJO implements Serializable {
private static final long serialVersionUID = 1L;
#Getter #Setter private Long id;
#Getter #Setter private Long date;
#Getter #Setter private Date name;
....
#Override
public String toString() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
//making a readable string-representation of the object to display on the orderList
public String toStringOrderlistDisplay() {
return "Pojo with id " + id + "and so on... "
}
In my frontend, I want to allow the user to sort this pojo-list using Primefaces orderList :
<p:orderList id="ordList" widgetVar="ordList"
value="#{backingview.pojoList }" var="rfg"
controlsLocation="left" responsive="true" itemValue="#{rfg}"
itemLabel="#{rfg.toStringOrderlistDisplay()}" converter="#{pojoConverter}">
</p:orderList>
PojoConverter.java
#Named
#FacesConverter(value = "pojoConverter")
public class PojoConverter implements Converter {
#Override
public Pojo getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && value.trim().length() > 0) {
try {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(value, RechtsaktFallgeschichte.class);
}
catch (NumberFormatException | IOException ex) {
ex.printStackTrace();
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid Pojo."));
}
}
else { return null; }
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
SomePOJO r = (SomePOJO) value;
if (r != null) {
return r.toString();
}
else { return null; }
}
}
Converting to JSON seems to work just fine, if I print the output of the getAsString() method, everything looks as you would expect. However, when the getAsObject() method is called, the value-String-parameter always contains "[object Object]" instead of the POJOs JSON representation. What am I doing wrong here?
I don't know if it is possible to achieve what you are trying to do, but a better way (and the working one) is to pass the POJO id in the getAsString() method, and convert it back to Pojo using a cache map Map<Long, Pojo> pojoCache.
The converter should look like this:
PojoConverter.java
#Named
#FacesConverter(value = "pojoConverter")
public class PojoConverter implements Converter<Pojo> {
#Inject
private PojoService pojoService;
#Override
public Pojo getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && value.trim().length() > 0) {
return pojoService.getPojoCache().get(Long.valueOf(value));
} else {
return null;
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Pojo value) {
if (value != null) {
return String.valueOf(value.getId());
} else {
return null;
}}
}
For a more detailed explanation check this: p:orderList converter getAsObject() doesn't call Object.toString()

p:orderList converter getAsObject() doesn't call Object.toString()

I've written a custom converter as follows:
#FacesConverter(value = "orderListConverter")
public class OrderListConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
Object ret = null;
if (component instanceof OrderList) {
Object list = ((OrderList) component).getValue();
ArrayList<ExampleEntity> al = (ArrayList<ExampleEntity>) list;
for (Object o : al) {
String name = "" + ((ExampleEntity) o).getName();
if (value.equals(name)) {
ret = o;
break;
}
}
}
return ret;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
String str = "";
if (value instanceof ExampleEntity) {
str = "" + ((ExampleEntity) value).getNumber();
}
return str;
}
}
My ExampleEntity is implemented as follows:
public class ExampleEntity {
private String name;
private int number;
public ExampleEntity(String name, int number) {
this.name = name;
this.number = number;
}
#Override
public String toString() {
return "toString(): [name=" + name + ", number=" + number + "]";
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
the orderList-Component from Primefaces looks like that:
<p:orderList value="#{orderListBean.exampleList}"
var="exampleEntity" itemValue="#{exampleEntity}"
converter="orderListConverter">
<p:column style="width:25%">
#{exampleEntity.number}
</p:column>
<p:column style="width:75%;">
#{exampleEntity.name}
</p:column>
</p:orderList>
and the bean is implemented as follows:
#SessionScoped
#ManagedBean(name = "orderListBean")
public class OrderListBean {
private List<ExampleEntity> exampleList;
#PostConstruct
public void init() {
exampleList = new ArrayList<ExampleEntity>();
exampleList.add(new ExampleEntity("nameOne", 1));
exampleList.add(new ExampleEntity("nameTwo", 2));
exampleList.add(new ExampleEntity("nameThree", 3));
exampleList.add(new ExampleEntity("nameFour", 4));
exampleList.add(new ExampleEntity("nameFive", 5));
}
public List<ExampleEntity> getExampleList() {
return exampleList;
}
public void setExampleList(List<ExampleEntity> exampleList) {
this.exampleList = exampleList;
}
}
1) when debugging, the value Parameter of getAsObject() contains
the number of the ExampleEntity, but I had expected the
toString() method of ExampleEntity to be called!
2) What is the correct content for itemValue attribute?
Is it a kind of convention over configuration? Or how does the component
'know', to use the whole object, when inserting exampleEntity into itemValue
Hope everything is clear! Tanks a lot for any explanation!
Converters basically serve to transform values in 2 directions:
Server to client, when the value is rendered.
Client to server, when the value is submitted.
In your getAsString you established, that the string representation, the one which client uses, is exampleEntity's number. So that's what gets rendered to client as a value. And later, when the client submits its value, that value is number. To convert it to the object (server) representation, the getAsObject called with the number as a parameter.
The server can't possibly call getAsObject with exampleEntity.toString(), because it doesn't have the exampleEntity instance at that point, only the submitted number.
To illustrate, this should hold:
obj.equals(conv.getAsObject(ctx, comp, conv.getAsString(ctx, comp, obj)));
getAsObject and getAsString should be inversive in their input and output.
To answer your 2nd question: that depends on your needs. You could say itemValue="#{exampleEntity.number}", but that would make sense only if you're not interested in the exampleEntity itself, i.e. on submit you would get the number from the client and that's all you need for your server-side logic.
#FacesConverter(value = "EntityConverter")
public class EntityConverter implements Converter, Serializable {
private static final long serialVersionUID = 1L;
public EntityConverter() {
super();
}
#Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value) {
if (value == null) {
return null;
}
return fromSelect(component, value);
}
/**
* #param currentcomponent
* #param objectString
* #return the Object
*/
private Object fromSelect(final UIComponent currentcomponent, final String objectString) {
if (currentcomponent.getClass() == UISelectItem.class) {
final UISelectItem item = (UISelectItem) currentcomponent;
final Object value = item.getValue();
if (objectString.equals(serialize(value))) {
return value;
}
}
if (currentcomponent.getClass() == UISelectItems.class) {
final UISelectItems items = (UISelectItems) currentcomponent;
final List<Object> elements = (List<Object>) items.getValue();
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
if (!currentcomponent.getChildren().isEmpty()) {
for (final UIComponent component : currentcomponent.getChildren()) {
final Object result = fromSelect(component, objectString);
if (result != null) {
return result;
}
}
}
if (currentcomponent instanceof OrderList) {
Object items = ((OrderList) currentcomponent).getValue();
List<Object> elements = (List<Object>) items;
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
return null;
}
/**
* #param object
* #return the String
*/
private String serialize(final Object object) {
if (object == null) {
return null;
}
return object.getClass() + "#" + object.hashCode();
}
#Override
public String getAsString(final FacesContext arg0, final UIComponent arg1, final Object object) {
return serialize(object);
}
}

Retrieve class values from selectCheckboxMenu

I have a <p:selectCheckboxMenu> and I want to get the selected values back in bean. But the value I receive
when I select an item from the menu it's a string, representing the type field from the CategorizationBean.
I just want when I select an item from the table, to get the whole CategorizationBean structure in the bean.
This is the snippet from the xhtml page:
<p:selectCheckboxMenu label="Categorization"
value="#alertMB.selectedCategories}"
converter="com.converter.CategoryConverter">
<f:selectItems value="#{alertMB.categoryDomainEntry}"
var="category"
itemLabel="#{category.type}"
itemValue="#{category}"/>
</p:selectCheckboxMenu>
Snippet from bean:
public List<CategorizationBean> getSelectedCategories() {
return selectedCategories;
}
public void setSelectedCategories(List<CategorizationBean> selectedCategories) {
this.selectedCategories = selectedCategories;
}
public class CategorizationBean implements Serializable{
private String type;
private long id;
I think that you have missed by using a list of beans, I use this example and it works:
<p:selectCheckboxMenu id="slctRdBtn"
value="#{yourBean.compLovDtgrid}"
converter="compLovDtgridConverter">
<f:selectItems
value="#{yourBean.listCompLovDtgrid}"
var="rdbtn" itemLabel="#{rdbtn.vjlrLibelleRep}"
itemValue="#{rdbtn}" />
</p:selectCheckboxMenu>
and for the converter:
#FacesConverter(forClass=CompLovDtgrid.class , value="compLovDtgridConverter")
public class CompLovDtgridConverter implements Converter{
#Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
return (value instanceof CompLovDtgrid) ? ((CompLovDtgrid) value).getVjlrCodeRep() : null;
}
#Override
public Object getAsObject(FacesContext context, UIComponent component,String value)
{
if(value == null)
return null;
YourBean data = context.getApplication().evaluateExpressionGet(context, "#{yourBean}", YourBean.class);
for(CompLovDtgrid compLovDtgrid : data.getListCompLovDtgrid())
{
if(compLovDtgrid.getVjlrCodeRep().equals(value))
return compLovDtgrid;
}
throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to CompLovDtgrid", value)));
}
}
and for the list, I use:
public List<CompLovDtgrid> getListCompLovDtgrid()
{
return listCompLovDtgrid;
}
public void setListCompLovDtgrid(List<CompLovDtgrid> listCompLovDtgrid) {
this.listCompLovDtgrid = listCompLovDtgrid;
}

How to use detached entitys + version in a JSF Converter

i have a problem with conversion of entitys with a version. I made a simple example to explain my problem because the "real" application is to big and contains many unnecessary things.
Situation: I have a web application with primefaces and openjpa. I have 20 components (autocompletes + selectedmenues) that needs a converter and they use persistence entitys.
Informations: I only want use jsf,primefaces for it! (Nothing special like omnifaces or something else.) The Question is at bottom. This is only test-code. It is NOT complete and there are some strange things. But this explain my problem at best.
Example entity: (Only fields and hashcode + equals)
#Entity
public class Person {
#Id
private Long id;
private String name;
#Version
private Long version;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
First solution: My first solution was that i make a own converter for every component.I inject my managed bean there and use the getter from the "value" of the component.
Bean
#ManagedBean(name = "personBean")
#ViewScoped
public class PersonBean implements Serializable {
private List<Person> persons;
/** unnecessary things **/
xhtml:
<p:selectOneMenu >
<f:selectItems value="#{personBean.persons}"/>
</p:selectOneMenu>
converter:
#ManagedBean
#RequestScoped
public class PersonConverter implements Converter{
#ManagedProperty(value = "personBean")
private PersonBean personBean;
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
//null & empty checks
Long id = Long.valueOf(value);
for(Person person : personBean.getPersons()){
if(person.getId().equals(id)){
return person;
}
}
throw new ConverterException("some text");
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
//null & Instanceof checks
return String.valueOf(((Person)value).getId());
}
}
Summary: This solution works good. But i found that there must be a better solution as an converter for every component.
Second solution: I found here on stackoverflow the Global Entity Converter. One converter for all, i thought that was a good solution. ("p:autocomplete for a global Entity Converter"). I use it and i thought it works fine. BUT after a few tests i found another big problem, the version of the entity.
Problem1 with entity converter:
I have the version field not in my hashcode or equals (i found nothing about it). I only read this (The JPA hashCode() / equals() dilemma) about it. The problem is that the entity will not replaced in the hashmap and in some cases i get an optimistic locking exception because the "old" entity stays in the hashmap.
if (!entities.containsKey(entity)) {
String uuid = UUID.randomUUID().toString();
entities.put(entity, uuid);
return uuid;
} else {
return entities.get(entity);
}
Solution: I thought that i can resolve this problem by adding an interface to my entitys that checks whether a version exists.
Interface:
public interface EntityVersionCheck {
public boolean hasVersion();
}
Implementation:
#Override
public boolean hasVersion() {
return true;
}
Converter:
#Override
public String getAsString(FacesContext context, UIComponent component, Object entity) {
synchronized (entities) {
if(entity instanceof EntityVersionCheck && ((EntityVersionCheck)entity).hasVersion()){
entities.remove(entity);
}
if (!entities.containsKey(entity)) {
String uuid = UUID.randomUUID().toString();
entities.put(entity, uuid);
return uuid;
} else {
return entities.get(entity);
}
}
}
This solution works for the optimistic locking exception but brings another problem!
Problem2 with entity converter:
<p:selectOneMenu value="#{organisation.leader}">
<f:selectItems value="#{personBean.persons}"/>
</p:selectOneMenu>
If a organisation has already a leader. It will be replaced with a new uuid if the leader is in the persons - list, too. The leader will be set to null or convert exception because the uuid does not exists anymore in the hashmap. It means he use the converter for the organisation.leader and add the leader to the hashmap. Than comes the persons- List and add all other persons in a hashmap and override the uuid from the organisation.leader if he exists in persons, too.
Here are two cases now:
When i select a other leader, it works normally.
If i dont change the "current" selection and submit the organisation.leader tries to find his "old" uuid but the other person from the person list has override it and the uuid does not exists and the organisation.leader is null.
I found another solution for it and this is my final solution BUT i find, that is a very very strange solution and i will do this better but i found nothing about it.
Final Solution
I add the "old" uuid to the "new" object.
#Override
public String getAsString(FacesContext context, UIComponent component,
Object entity) {
synchronized (entities) {
String currentuuid = null;
if (entity instanceof EntityVersionCheck
&& ((EntityVersionCheck) entity).hasVersion()) {
currentuuid = entities.get(entity);
entities.remove(entity);
}
if (!entities.containsKey(entity)) {
if (currentuuid == null) {
currentuuid = UUID.randomUUID().toString();
}
entities.put(entity, currentuuid);
return currentuuid;
} else {
return entities.get(entity);
}
}
}
Question: How i make this better and right?
If Solution 1 worked and you just want it more generic:
Holding your instances within scope of a bean you can use a more generic converter by removing the managed-bean lookup from it. Your entities should inherit from a base entity with a identifier property. You can instantiate this converter in your bean where you retrieved the entities.
Or use a guid map or public identifier if id should not be exposed in html source.
#ManagedBean(name = "personBean")
#ViewScoped
public class PersonBean implements Serializable {
private List<Person> persons;
private EntityConverter<Person> converter;
// this.converter = new EntityConverter<>(persons);
}
<p:selectOneMenu converter="#{personBean.converter}">
<f:selectItems value="#{personBean.persons}"/>
</p:selectOneMenu>
Abstract Base Entity converter:
/**
* Abstract Entity Object JSF Converter which by default converts by {#link Entity#getId()}
*/
public abstract class AEntityConverter<T extends Entity> implements Converter
{
#Override
public String getAsString(final FacesContext context, final UIComponent component, final Object value)
{
if (value instanceof Entity)
{
final Entity entity = (Entity) value;
if (entity.getId() != null)
return String.valueOf(entity.getId());
}
return null;
}
}
Cached collection:
/**
* Entity JSF Converter which holds a Collection of Entities
*/
public class EntityConverter<T extends Entity> extends AEntityConverter<T>
{
/**
* Collection of Entity Objects
*/
protected Collection<T> entities;
/**
* Creates a new Entity Converter with the given Entity Object's
*
* #param entities Collection of Entity's
*/
public EntityConverter(final Collection<T> entities)
{
this.entities = entities;
}
#Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value)
{
if (value == null || value.trim().equals(""))
return null;
try
{
final int id = Integer.parseInt(value);
for (final Entity entity : this.entities)
if (entity.getId().intValue() == id)
return entity;
}
catch (final RuntimeException e)
{
// do something --> redirect to exception site
}
return null;
}
#Override
public void setEntities(final Collection<T> entities)
{
this.entities = entities;
}
#Override
public Collection<T> getEntities()
{
return this.entities;
}
}
Remote or database lookup Converter:
/**
* Entity Object JSF Converter
*/
public class EntityRemoteConverter<T extends Entity> extends AEntityConverter<T>
{
/**
* Dao
*/
protected final Dao<T> dao;
public EntityRemoteConverter(final EntityDao<T> dao)
{
this.dao = dao;
}
#Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value)
{
// check for changed value
// no need to hit database or remote server if value did not changed!
if (value == null || value.trim().equals(""))
return null;
try
{
final int id = Integer.parseInt(value);
return this.dao.getEntity(id);
}
catch (final RuntimeException e)
{
// do someting
}
return null;
}
}
I use dao approach whenever I have to convert view-parameters and bean was not constructed yet.
Avoid expensive lookups
In dao approach you should check if the value has changed before doing potential expensive lookups, since converters could be called multiple times within different phases.
Have a look at source of: http://showcase.omnifaces.org/converters/ValueChangeConverter
This basic approach is very flexible and can be extended easily for many use cases.

Primefaces p:orderList java backing list does not update

I am currently implementing a orderable list using PrimeFaces' component, embedded inside a . I was able to get the list to appear properly with my items. However, when I saved the list and submitted it back to the server, the rearranged items did not get reflected in the backing bean for some reason. Since the Primefaces showcase was able to see the changes, what am I doing wrong?
XHTML Snippet:
<h:form id="confirmDialogForm">
<p:confirmDialog id="arrangeProjDialog" widgetVar="arrangeDlg" width="600"
header="Meeting Order"
appendToBody="true" message="Drag and drop to rearrange meeting order">
<p:orderList id="arrangeProjDialogList"
value="#{adminMeetingListBean.orderProjList}"
converter="#{adminMeetingListBean.rowConverter}"
var="po"
controlsLocation="left"
styleClass="wideList"
itemLabel="#{po.projectTitle}"
itemValue="#{po}"
>
<f:facet name="caption">Proposals</f:facet>
</p:orderList>
<p:commandButton value="Save" ajax="true" process="arrangeProjDialogList #this"
actionListener="#{adminMeetingListBean.updateProposalMeetingOrder}" onclick="arrangeDlg.hide();">
</p:commandButton>
<p:button value="Cancel" onclick="arrangeDlg.hide(); return false;" />
</p:confirmDialog>
</h:form>
Backing Bean:
public void updateProposalMeetingOrder() {
if (selectedMeeting != null) {
orderProjTitles.get(0);
meetingService.updateMeetingProjSequence(orderProjList, selectedMeeting.getMeetingId());
}
}
The List is a list of POJO "ProposalOrderRow" objects. This has the definition:
public class ProposalOrderRow implements Serializable {
private static final long serialVersionUID = -5012155654584965160L;
private int dispSeq;
private int appId;
private int assignmentId;
private String refNo;
private String projectTitle;
public int getDispSeq() {
return dispSeq;
}
public void setDispSeq(int dispSeq) {
this.dispSeq = dispSeq;
}
public int getAppId() {
return appId;
}
public void setAppId(int appId) {
this.appId = appId;
}
public String getRefNo() {
return refNo;
}
public void setRefNo(String refNo) {
this.refNo = refNo;
}
public String getProjectTitle() {
return projectTitle;
}
public void setProjectTitle(String projectTitle) {
this.projectTitle = projectTitle;
}
public int getAssignmentId() {
return assignmentId;
}
public void setAssignmentId(int assignmentId) {
this.assignmentId = assignmentId;
}
}
Converter:
#FacesConverter("proposalOrderRowConverter")
public class ProposalOrderRowConverter implements Converter {
private List<ProposalOrderRow> orderRows;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String newValue) {
if (newValue.isEmpty()) {
return null;
}
for (ProposalOrderRow item : orderRows) {
String refNo = item.getRefNo();
if (refNo.equals(newValue)) {
return item;
}
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
ProposalOrderRow row = (ProposalOrderRow) value;
String output = row.getRefNo();
return output;
}
public List<ProposalOrderRow> getOrderRows() {
return orderRows;
}
public void setOrderRows(List<ProposalOrderRow> orderRows) {
this.orderRows = orderRows;
}
}
This problem is caused by appendToBody="true" in the confirm dialog. Setting it to false solved the problem.
See link here: link

Resources