I got a problem using selectOneMenu, it can clearly convert the Suppliers to SupplierBean (my boss use to call it that way-he was the one who set it up), and display it correctly on the page, but the moment i save it, it returns a null value.
My code in XHTML:
<p:selectOneMenu value="#{itemSupplierController.supplierBean}"
converter="supplierConverter">
<f:selectItem itemLabel="Select..." itemValue="" />
<f:selectItems value="#{supplierController.suppliersBean}"
var="s" itemValue="#{s}" itemLabel="#{s.supplierName}" />
</p:selectOneMenu>
Code in SupplierBean:
public class SupplierBean {
private int id;
private String supplierName;
public SupplierBean(){
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSupplierName() {
return supplierName;
}
public void setSupplierName(String supplierName) {
this.supplierName = supplierName;
}
}
Code for converter:
#FacesConverter(value = "supplierConverter")
public class SupplierConverter implements Converter {
private static final Logger logger = Logger.getLogger("SupplierConverter");
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String id) {
logger.info(id);
SupplierManager manager = EjbInitializer.getSupplierManager();
if (StringUtils.isNullOrEmpty(id)
|| !org.apache.commons.lang.math.NumberUtils.isNumber(id)) {
return null;
} else {
SupplierBean sb = null;
try {
sb = convertToPojo((Supplier) manager.find(Integer.valueOf(id)));
} catch (SoftTechPersistenceException e) {
e.printStackTrace();
}
return sb;
}
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object s) {
String val = null;
logger.info("object: " + s);
if (s != null && (s instanceof SupplierBean)) {
SupplierBean supplier = (SupplierBean) s;
val = Integer.toString(supplier.getId());
}
logger.info(String.format("value %s", val));
return val;
}
public static SupplierBean convertToPojo(Supplier s) {
SupplierBean supplier = new SupplierBean();
supplier.setId(s.getId());
String name = "";
if (s.getFullName().isEmpty()) {
name = s.getFullName();
} else {
name = s.getCompany();
}
supplier.setSupplierName(name);
return supplier;
}
}
Overview of the methods in my backingBean that i use to save the supplier(I used to call it controller):
public void supplierSave() {
logger.info("supplier save or update commenced.");
if (SupplierAction.Create.equals(supplierCurrentAction)) {
logger.info("adding supplier to the table...");
addSupplierToTable();
} else if (SupplierAction.Update.equals(supplierCurrentAction)) {
logger.info("supplier updating...");
updateSupplier();
}
}
public void addSupplierToTable() {
try {
logger.info(String.format("supplier id: %s", getSupplierBean().getId()));
setSupplier((Supplier)supplierManager.find(getSupplierBean().getId()));
getItemSupplier().setSupplier(getSupplier());
getItemSuppliers().add(getItemSupplier());
resetSupplier();
} catch (Exception e) {
e.printStackTrace();
}
logger.info("supplier successfully added to the table.");
}
Related
I'm trying to implement pagination for a project that loads a large set of data from the database.
I've done a lot of searching on the internet already to get db-pagination to work, but for some reason I still don't get it working the way I want.
I've followed the example as described in this topic:
JSF, RichFaces, pagination
The data is loaded, so that works; cache also seems to work. However, it seems to still load all the data. The sr.getRows() in the walk-method is always -1, so the call to the database also uses -1 for maxResults. I get all my data, but no pagination.
I don't want to introduce another dependency if I can avoid it.
Some of my data:
BatchDataModel
public abstract class BatchDataModel<T> extends ExtendedDataModel<T> {
private SequenceRange cachedRange;
private Integer cachedRowCount;
private List<T> cachedList;
private Object rowKey;
public abstract List<T> getDataList(int firstRow, int numRows);
public abstract Object getKey(T t);
public abstract int getTotalCount();
#Override
public void walk(FacesContext ctx, DataVisitor dv, Range range, Object argument) {
SequenceRange sr = (SequenceRange) range;
if (cachedList == null || !equalRanges(cachedRange, sr)) {
cachedList = getDataList(sr.getFirstRow(), sr.getRows());
cachedRange = sr;
}
for (T t : cachedList) {
if (getKey(t) == null) {
/*
* the 2nd param is used to build the client id of the table
* row, i.e. mytable:234:inputname, so don't let it be null.
*/
throw new IllegalStateException("found null key");
}
dv.process(ctx, getKey(t), argument);
}
}
/*
* The rowKey is the id from getKey, presumably obtained from
* dv.process(...).
*/
#Override
public void setRowKey(Object rowKey) {
this.rowKey = rowKey;
}
#Override
public Object getRowKey() {
return rowKey;
}
#Override
public boolean isRowAvailable() {
return (getRowData() != null);
}
#Override
public int getRowCount() {
if (cachedRowCount == null) {
cachedRowCount = getTotalCount();
}
return cachedRowCount;
}
#Override
public T getRowData() {
for (T t : cachedList) {
if (getKey(t).equals(this.getRowKey())) {
return t;
}
}
return null;
}
protected static boolean equalRanges(SequenceRange range1, SequenceRange range2) {
if (range1 == null || range2 == null) {
return range1 == null && range2 == null;
} else {
return range1.getFirstRow() == range2.getFirstRow() && range1.getRows() == range2.getRows();
}
}
/*
* get/setRowIndex are used when doing multiple select in an
* extendedDataTable, apparently. Not tested. Actually, the get method is
* used when using iterationStatusVar="it" & #{it.index}.
*/
#Override
public int getRowIndex() {
if (cachedList != null) {
ListIterator<T> it = cachedList.listIterator();
while (it.hasNext()) {
T t = it.next();
if (getKey(t).equals(this.getRowKey())) {
return it.previousIndex() + cachedRange.getFirstRow();
}
}
}
return -1;
}
#Override
public void setRowIndex(int rowIndex) {
int upperBound = cachedRange.getFirstRow() + cachedRange.getRows();
if (rowIndex >= cachedRange.getFirstRow() && rowIndex < upperBound) {
int index = rowIndex % cachedRange.getRows();
T t = cachedList.get(index);
setRowKey(getKey(t));
}
}
#Override
public Object getWrappedData() {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void setWrappedData(Object data) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<T> getCachedList() {
return cachedList;
}
Bean (part)
private ListState state;
private BatchDataModel<Batch> model;
public BatchDataModel<Batch> getModel(){
return model;
}
public int getCurrentPage() {
return state.getPage();
}
public void setCurrentPage(int page) {
state.setPage(page);
}
public void setBatchService(BatchService batchService) {
this.batchService = batchService;
}
/**
* Initialize the variables, before the page is shown.
*/
#PostConstruct
private void init() {
filter = new Filter();
sorter = new Sorter();
state = getFromSession("batchList", null);
if (state == null) {
state = new ListState();
storeInSession("batchList", state);
}
}
public void loadBatches(boolean search) {
BatchDataModel<Batch> model = new BatchDataModel<Batch>(){
#Override
public List<Batch> getDataList(int firstRow, int numRows) {
try {
List <Batch> test;
test = batchService.selectBatches(userBean.getUser(), firstRow, numRows);
return test;
} catch (NozemException e) {
LOGGER.error(e.getMessage());
sendMessage(e.getMessage(), true);
return null;
}
}
#Override
public Object getKey(Batch batch) {
return batch.getBatchId();
}
#Override
public int getTotalCount() {
try {
return batchService.countBatches(userBean.getUser());
} catch (NozemException e) {
LOGGER.error(e.getMessage());
sendMessage(e.getMessage(), true);
return 0;
}
}
};
}
xhtml (part)
<rich:dataTable id="batchesTable" rows="2"
value="#{batchBean.model}" var="batch" first="#{batchBean.currentPage}"
styleClass="table" rowClasses="odd-row, even-row"
onrowmouseover="this.style.backgroundColor='#88B5F9'"
onrowmouseout="this.style.backgroundColor='#{a4jSkin.rowBackgroundColor}'">
(...)
<f:facet name="footer">
<rich:dataScroller page="#{batchBean.currentPage}" />
</f:facet>
ArrangeableModel is the key. This class needs to be implemented in the BatchDataModel class, together with a method and function. This way the same state is used and the walk-method gets the correct values in SequenceRange.
public abstract class BatchDataModel<T> extends ExtendedDataModel<T> implements Arrangeable {
private ArrangeableState arrangeableState;
public void arrange(FacesContext context, ArrangeableState state) {
arrangeableState = state;
}
protected ArrangeableState getArrangeableState() {
return arrangeableState;
}
}
How can I pass an injected http session attribute (see below), along with other values (informe by the user) and save them using JPA?
The session attribute is correctly displayed and injected, but I need to pass it using the selected to be stored in the database (actually, it passess null).
The JSF:
<p:outputLabel value="UserID (the sessionAttribute):" for="userID" />
<p:inputText id="userID" value="#{userBean.myUser.xChave}" title="userID" />
<p:outputLabel value="Type the Reason:" for="reason" />
<p:inputText id="reason" value="#{viagensController.selected.reason}" />
<!-- updated (just the call to the action method: -->
<p:commandButton actionListener="#{viagensController.saveNew}" value="#{viagensBundle.Save}" update="display,:ViagensListForm:datalist,:growl" oncomplete="handleSubmit(xhr,status,args,ViagensCreateDialog);" />
The bean:
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
#Named(value = "userBean")
#SessionScoped
public class UserBean implements Serializable {
private bean_login myUser;
public bean_login getMyUser() {
return myUser;
}
public void setMyUser(bean_login myUser) {
this.myUser = myUser;
}
#PostConstruct
public void init() {
String uid = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("xChave").toString();
myUser = new bean_login();
myUser.setxChave(uid);
System.out.print("from init:" + myUser.toString());
}
}
The AbstractFacade:
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {{ /*impl. ommited*/ }
public List<T> findAll() {{ /*impl. ommited*/ }
public List<T> findRange(int[] range) { /*impl. ommited*/ }
public int count() { /*impl. ommited*/ }
}
The AbstractController (for the selected in JSF above and other methods):
public abstract class AbstractController<T> {
#Inject
private AbstractFacade<T> ejbFacade;
private Class<T> itemClass;
private T selected;
private Collection<T> items;
private enum PersistAction {
CREATE,
DELETE,
UPDATE
}
public AbstractController() {
}
public AbstractController(Class<T> itemClass) {
this.itemClass = itemClass;
}
public T getSelected() {
return selected;
}
// Pass in the currently selected item
public void setSelected(T selected) {
this.selected = selected;
}
protected void setEmbeddableKeys() {
}
protected void initializeEmbeddableKey() {
}
public Collection<T> getItems() {
if (items == null) {
items = this.ejbFacade.findAll();
}
return items;
}
// Pass in collection of items
public void setItems(Collection<T> items) {
this.items = items;
}
// Apply changes to an existing item to the data layer.
public void save(ActionEvent event) {
String msg = ResourceBundle.getBundle("/viagensBundle").getString(itemClass.getSimpleName() + "Updated");
persist(PersistAction.UPDATE, msg);
}
// Store a new item in the data layer.
public void saveNew(ActionEvent event) {
String msg = ResourceBundle.getBundle("/viagensBundle").getString(itemClass.getSimpleName() + "Created");
persist(PersistAction.CREATE, msg);
if (!isValidationFailed()) {
items = null; // Invalidate list of items to trigger re-query.
}
}
public void delete(ActionEvent event) {/*implementations ommited*/ }
private void persist(PersistAction persistAction, String successMessage) {
if (selected != null) {
this.setEmbeddableKeys();
try {
if (persistAction != PersistAction.DELETE) {
this.ejbFacade.edit(selected);
} else {
this.ejbFacade.remove(selected);
}
JsfUtil.addSuccessMessage(successMessage);
} catch (EJBException ex) {
String msg = "";
Throwable cause = JsfUtil.getRootCause(ex.getCause());
if (cause != null) {
if (cause instanceof ConstraintViolationException) {
ConstraintViolationException excp = (ConstraintViolationException) cause;
for (ConstraintViolation s : excp.getConstraintViolations()) {
JsfUtil.addErrorMessage(s.getMessage());
}
} else {
msg = cause.getLocalizedMessage();
if (msg.length() > 0) {
JsfUtil.addErrorMessage(msg);
} else {
JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
}
}
}
} catch (Exception ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/viagensBundle").getString("PersistenceErrorOccured"));
}
}
}
// Creates a new instance of an underlying entity and assigns it to Selected property.
public T prepareCreate(ActionEvent event) {
T newItem;
try {
newItem = itemClass.newInstance();
this.selected = newItem;
initializeEmbeddableKey();
return newItem;
} catch (InstantiationException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
return null;
}
// Inform the user interface whether any validation error exist on a page.
public boolean isValidationFailed() {
return JsfUtil.isValidationFailed();
}
// Retrieve all messages as a String to be displayed on the page.
public String getComponentMessages(String clientComponent, String defaultMessage) {
return JsfUtil.getComponentMessages(clientComponent, defaultMessage);
}
}
Thanks in advance.
updated:
The ViagensController:
#Named(value = "viagensController")
#ViewScoped
public class ViagensController extends AbstractController<Viagens> implements Serializable {
//generics:passing JPA Entity class, where the 'reason' in JSF is defined
public ViagensController() {
super(Viagens.class);
}
}
Need to override the save method passing the injected http session value :
#ManagedBean(name = "riscosController")
#ViewScoped
public class RiscosController extends AbstractController<Riscos> {
#EJB
private RiscosFacade ejbFacade;
#Inject
#SessionChave
private String iSessionChave;
private String sessionChave;
private UorPosController matriculaController;
private UorPosController informanteController;
public String getSessionChave(String chave) {
if (sessionChave.isEmpty()) {
sessionChave = iSessionChave;
}
return sessionChave;
}
public void setSessionChave(String sessionChave) {
this.sessionChave = sessionChave;
}
#PostConstruct
#Override
public void init() {
super.setFacade(ejbFacade);
FacesContext context = FacesContext.getCurrentInstance();
matriculaController = context.getApplication().evaluateExpressionGet(context, "#{uorPosController}", UorPosController.class);
informanteController = context.getApplication().evaluateExpressionGet(context, "#{uorPosController}", UorPosController.class);
sessionChave = "";
}
#Override
public void saveNew(ActionEvent event) {
this.getSelected().setObs(this.getSessionChave(sessionChave));
super.saveNew(event);
}
}
I try to use the pickList component of Primefaces. My converter does not work properly and I don't know why.
This is my ManagedBean:
#ManagedBean(name = "comMB")
#SessionScoped
public class TeamCompetitionBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private DualListModel<Team> teams;
List<Team> source;
List<Team> source1;
List<Team> target;
#ManagedProperty("#{team}")
private TeamServiceI teamService;
List<String> teamNameList ;
// public TeamCompetitionBean() {
public DualListModel<Team> getTeams() {
// Players
teamNameList = new ArrayList<String>();
source = new ArrayList<Team>();
target = new ArrayList<Team>();
source.addAll(getTeamService().getTeam());
teams = new DualListModel<Team>(source, target);
return teams;
}
public void setTeams(DualListModel<Team> teams) {
this.teams = teams;
}
public void onTransfer(TransferEvent event) {
StringBuilder builder = new StringBuilder();
for (Object item : event.getItems()) {
builder.append(((Team) item).getTeamName()).append("<br />");
}
FacesMessage msg = new FacesMessage();
msg.setSeverity(FacesMessage.SEVERITY_INFO);
msg.setSummary("Items Transferred");
msg.setDetail(builder.toString());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public TeamServiceI getTeamService() {
return teamService;
}
public void setTeamService(TeamServiceI teamService) {
this.teamService = teamService;
}
public List<Team> getSource() {
return source;
}
public void setSource(List<Team> source) {
this.source = source;
}
public List<Team> getTarget() {
return target;
}
public void setTarget(List<Team> target) {
this.target = target;
}
public void afficher(){
System.out.println(target);
System.out.println(source);
}
}
and this is my entity class that I would like to load in my pickList:
#Entity
#Table(name = "team", catalog = "competition_manager")
public class Team implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer idTeam;
private Stadium stadium;
private League league;
private String teamName;
// getters and setters
#Override
public String toString() {
return teamName.toString();
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof Team)) {
return false;
}
Team f = (Team) obj;
return (this.idTeam == f.getIdTeam());
}
Now, this is my custom Converter:
#FacesConverter(forClass = Team.class, value = "teamConverter")
public class TeamConverter implements Converter {
Team team;
public Object getAsObject(FacesContext facesContext, UIComponent component,
String value) {
System.out.println("hello object");
if (value == null || value.length() == 0) {
return null;
}
ApplicationContext ctx = FacesContextUtils
.getWebApplicationContext(FacesContext.getCurrentInstance());
TeamBean controller = (TeamBean) ctx.getBean("teamMB");
List<Team> liststagiaire = controller.getTeamList();
for (int i = 0; i < liststagiaire.size(); i++)
{
team = liststagiaire.get(i);
if (team.getIdTeam() == getKey(value)) {
break;
}
}
return team;
}
java.lang.Integer getKey(String value) {
java.lang.Integer key;
key = Integer.valueOf(value);
return key;
}
String getStringKey(java.lang.Integer value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent component,
Object object) {
System.out.println("hello string");
if (object == null) {
System.out.println("hello string null");
return null;
}
if (object instanceof Team) {
System.out.println("hello string intance of");
Team o = (Team) object;
String i = getStringKey(o.getIdTeam());
return i;
} else {
System.out.println("hello throw");
throw new IllegalArgumentException("object " + object
+ " is of type " + object.getClass().getName()
+ "; expected type: " + Team.class.getName());
}
}
}
And finally this is my XHTML page:
<p:pickList id="teamPickList" value="#{comMB.teams}" var="team"
itemValue="#{team}" itemLabel="#{team}" converter="teamConverter">
</p:pickList>
Your problem is comming from this line (in your class TeamConverter) :
if (team.getIdTeam() == getKey(value)) {
You can't compare Integer objects like that, because doing like this you are comparing reference. You should replace this line by
if (team.getIdTeam().intValue() == getKey(value).intValue()) {
You have the same problem in your class Team :
return (this.idTeam == f.getIdTeam());
should be replaced by :
return (this.idTeam.intValue() == f.getIdTeam().intValue());
Not related :
You don't need to use getKey and getStringKey, you could replace them simply like this :
getKey(value) // this
Integer.valueOf(value) // by this
and
getStringKey(o.getIdTeam()) // this
o.getIdTeam().toString() // by this
Also you should replace itemLabel="#{team}" by itemLabel="#{team.teamName}" in your view.
My web application is a CRUD web application based on JSF 2.0 / JPA using Java EE 5 and JDK 1.6. Running on Glassfish 3.1. The IDE is Netbeans 7.0. (I do not use EJB, nor CDI).
THE PROBLEM
What I can achieve now is perform CRUD on my entities. Which is fine. For each entity I have:
List.xhtml (LIsting all Datamodel items for that entity in datatable)
Create.xhtml (A form to create a new item)
View.xhtml (a form to view an item)
Edit.xhtml (a form to edit an item)
Structure
entities package: entities.
jpa.controllers package: JPA controllers (Javax persistence..).
jsf package: a managed bean for each entity (session Scoped).
But the main problem is parent-leaf navigation. I want my webapp to do the same thing as the Demo application Agile ScrumToys that comes along shipped with Netbeans 7.0. or the demo webapp from SpringFuse, otherwise :
E.G: When you display a list of WRITERS in a you have the last <h:column> where you put three <h:commandLink /> for editing, viewing and deleting the selected row.
What I intend to do is to add another in the same column that allows me to view a collection of child objects related to that selected row.
Hence, I want to show the list of BOOKS written by a given WRITER.
WRITER 1 ---------- * BOOK (one-to-many) relationship.
When the user clicks on the
<h:commandButton action="#{someManagedBean.showBooksForWriter}" value="#{i18n.listBooks}" /> it forwards him to the /book/List.xhtml (list of the selected WRITEr row should appear). And so on, from the book datatable, from a given row, I click on <h:commandLink action="#{someManagedBean.showReferencesForBook}" value="List of Book References"/> to get the list of references for the given book.
A given hint by #Matt was to use a method in the book managed bean:
public showBooksForWriter(Writer writer) {
// TODO: get the selected writer
// Get the list of books for the selected writer
return "/book/List"; // Outcome
}
And in the view :
<h:datatable value="#{writerController.items}" var="w">
.....
<h:column>
<h:commandButton action="#{bookController.showBooksForWriter(w}" value="Show Books For Writer"/>
</h:column>
....
</h:datatable>
But I could not figure how to (DataModel is driving mad). So if anyone could help! It would be very appreciated!
Below is my code
the WRITER entity:
package entities;
import javax.persistence.*; // other imports
#Entity
#Table(name = "WRITER")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Writer.findAll", query = "SELECT w FROM Writer w"),
#NamedQuery(name = "Writer.findByWriterid", query = "SELECT w FROM Writer w WHERE w.writerid = :writerid"),
#NamedQuery(name = "Writer.findByName", query = "SELECT w FROM Writer w WHERE w.name = :name"),
#NamedQuery(name = "Writer.findBySurname", query = "SELECT w FROM Writer w WHERE w.surname = :surname"),
#NamedQuery(name = "Writer.findByMiddlename", query = "SELECT w FROM Writer w WHERE w.middlename = :middlename"),
#NamedQuery(name = "Writer.findByIsRewarded", query = "SELECT w FROM Writer w WHERE w.isRewarded = :isRewarded")})
public class Writer implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#NotNull
#Column(name = "writerid")
private Integer writerid;
#Size(max = 45)
#Column(name = "name")
private String name;
#Size(max = 45)
#Column(name = "surname")
private String surname;
#Size(max = 45)
#Column(name = "middlename")
private String middlename;
#Column(name = "isRewarded")
private Boolean isRewarded;
#ManyToMany(mappedBy = "writerList")
private List<Topic> topicList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "writer")
private List<Evaluation> evaluationList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "writer")
private List<Book> bookList;
public Writer() {
}
public Writer(Integer writerid) {
this.writerid = writerid;
}
public Integer getWriterid() {
return writerid;
}
public void setWriterid(Integer writerid) {
this.writerid = writerid;
}
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 String getMiddlename() {
return middlename;
}
public void setMiddlename(String middlename) {
this.middlename = middlename;
}
public Boolean getIsRewarded() {
return isRewarded;
}
public void setIsRewarded(Boolean isRewarded) {
this.isRewarded = isRewarded;
}
#XmlTransient
public List<Topic> getTopicList() {
return topicList;
}
public void setTopicList(List<Topic> topicList) {
this.topicList = topicList;
}
#XmlTransient
public List<Evaluation> getEvaluationList() {
return evaluationList;
}
public void setEvaluationList(List<Evaluation> evaluationList) {
this.evaluationList = evaluationList;
}
#XmlTransient
public List<Book> getBookList() {
return bookList;
}
public void setBookList(List<Book> bookList) {
this.bookList = bookList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (writerid != null ? writerid.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Writer)) {
return false;
}
Writer other = (Writer) object;
if ((this.writerid == null && other.writerid != null) || (this.writerid != null && !this.writerid.equals(other.writerid))) {
return false;
}
return true;
}
#Override
public String toString() {
return getMiddlename();
}
}
The Writer MANAGED BEAN
package jsf;
import entities.Writer;
import jsf.util.JsfUtil;
import jsf.util.PaginationHelper;
import jpa.controllers.WriterJpaController;
import javax.faces.bean.ManagedBean;
// other imports here
#ManagedBean(name = "writerController")
#SessionScoped
public class WriterController implements Serializable {
#Resource
private UserTransaction utx = null;
#PersistenceUnit(unitName = "writerPU")
private EntityManagerFactory emf = null;
private Writer current;
private DataModel items = null;
private WriterJpaController jpaController = null;
private PaginationHelper pagination;
private int selectedItemIndex;
public WriterController() {
}
public Writer getSelected() {
if (current == null) {
current = new Writer();
selectedItemIndex = -1;
}
return current;
}
private WriterJpaController getJpaController() {
if (jpaController == null) {
jpaController = new WriterJpaController(utx, emf);
}
return jpaController;
}
public PaginationHelper getPagination() {
if (pagination == null) {
pagination = new PaginationHelper(10) {
#Override
public int getItemsCount() {
return getJpaController().getWriterCount();
}
#Override
public DataModel createPageDataModel() {
return new ListDataModel(getJpaController().findWriterEntities(getPageSize(), getPageFirstItem()));
}
};
}
return pagination;
}
public String prepareList() {
recreateModel();
return "List";
}
public String prepareView() {
current = (Writer) getItems().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
return "View";
}
public String prepareCreate() {
current = new Writer();
selectedItemIndex = -1;
return "Create";
}
public String create() {
try {
getJpaController().create(current);
JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterCreated"));
return prepareCreate();
} catch (Exception e) {
JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
return null;
}
}
public String prepareEdit() {
current = (Writer) getItems().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
return "Edit";
}
public String update() {
try {
getJpaController().edit(current);
JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterUpdated"));
return "View";
} catch (Exception e) {
JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
return null;
}
}
public String destroy() {
current = (Writer) getItems().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
performDestroy();
recreateModel();
return "List";
}
public String destroyAndView() {
performDestroy();
recreateModel();
updateCurrentItem();
if (selectedItemIndex >= 0) {
return "View";
} else {
// all items were removed - go back to list
recreateModel();
return "List";
}
}
private void performDestroy() {
try {
getJpaController().destroy(current.getWriterid());
JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterDeleted"));
} catch (Exception e) {
JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
}
}
private void updateCurrentItem() {
int count = getJpaController().getWriterCount();
if (selectedItemIndex >= count) {
// selected index cannot be bigger than number of items:
selectedItemIndex = count - 1;
// go to previous page if last page disappeared:
if (pagination.getPageFirstItem() >= count) {
pagination.previousPage();
}
}
if (selectedItemIndex >= 0) {
current = getJpaController().findWriterEntities(1, selectedItemIndex).get(0);
}
}
public DataModel getItems() {
if (items == null) {
items = getPagination().createPageDataModel();
}
return items;
}
private void recreateModel() {
items = null;
}
public String next() {
getPagination().nextPage();
recreateModel();
return "List";
}
public String previous() {
getPagination().previousPage();
recreateModel();
return "List";
}
public SelectItem[] getItemsAvailableSelectMany() {
return JsfUtil.getSelectItems(getJpaController().findWriterEntities(), false);
}
public SelectItem[] getItemsAvailableSelectOne() {
return JsfUtil.getSelectItems(getJpaController().findWriterEntities(), true);
}
#FacesConverter(forClass = Writer.class)
public static class WriterControllerConverter implements Converter {
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
WriterController controller = (WriterController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "writerController");
return controller.getJpaController().findWriter(getKey(value));
}
java.lang.Integer getKey(String value) {
java.lang.Integer key;
key = Integer.valueOf(value);
return key;
}
String getStringKey(java.lang.Integer value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Writer) {
Writer o = (Writer) object;
return getStringKey(o.getWriterid());
} else {
throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + WriterController.class.getName());
}
}
}
}
JSF Utility Class
package jsf.util;
import javax.faces.application.FacesMessage;
// Other imports here
public class JsfUtil {
public static SelectItem[] getSelectItems(List<?> entities, boolean selectOne) {
int size = selectOne ? entities.size() + 1 : entities.size();
SelectItem[] items = new SelectItem[size];
int i = 0;
if (selectOne) {
items[0] = new SelectItem("", "---");
i++;
}
for (Object x : entities) {
items[i++] = new SelectItem(x, x.toString());
}
return items;
}
public static void addErrorMessage(Exception ex, String defaultMsg) {
String msg = ex.getLocalizedMessage();
if (msg != null && msg.length() > 0) {
addErrorMessage(msg);
} else {
addErrorMessage(defaultMsg);
}
}
public static void addErrorMessages(List<String> messages) {
for (String message : messages) {
addErrorMessage(message);
}
}
public static void addErrorMessage(String msg) {
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
FacesContext.getCurrentInstance().addMessage(null, facesMsg);
}
public static void addSuccessMessage(String msg) {
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
FacesContext.getCurrentInstance().addMessage("successInfo", facesMsg);
}
public static String getRequestParameter(String key) {
return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(key);
}
public static Object getObjectFromRequestParameter(String requestParameterName, Converter converter, UIComponent component) {
String theId = JsfUtil.getRequestParameter(requestParameterName);
return converter.getAsObject(FacesContext.getCurrentInstance(), component, theId);
}
}
JSF Pagination helper
package jsf.util;
import javax.faces.model.DataModel;
public abstract class PaginationHelper {
private int pageSize;
private int page;
public PaginationHelper(int pageSize) {
this.pageSize = pageSize;
}
public abstract int getItemsCount();
public abstract DataModel createPageDataModel();
public int getPageFirstItem() {
return page * pageSize;
}
public int getPageLastItem() {
int i = getPageFirstItem() + pageSize - 1;
int count = getItemsCount() - 1;
if (i > count) {
i = count;
}
if (i < 0) {
i = 0;
}
return i;
}
public boolean isHasNextPage() {
return (page + 1) * pageSize + 1 <= getItemsCount();
}
public void nextPage() {
if (isHasNextPage()) {
page++;
}
}
public boolean isHasPreviousPage() {
return page > 0;
}
public void previousPage() {
if (isHasPreviousPage()) {
page--;
}
}
public int getPageSize() {
return pageSize;
}
} // END of CLASS
The JPA Controller
package jpa.controllers;
import entities.Writer;
// other imports here
public class WriterJpaController implements Serializable {
public WriterJpaController(UserTransaction utx, EntityManagerFactory emf) {
this.utx = utx;
this.emf = emf;
}
private UserTransaction utx = null;
private EntityManagerFactory emf = null;
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void create(Writer writer) throws RollbackFailureException, Exception {
if (writer.getTopicList() == null) {
writer.setTopicList(new ArrayList<Topic>());
}
if (writer.getEvaluationList() == null) {
writer.setEvaluationList(new ArrayList<Evaluation>());
}
if (writer.getBookList() == null) {
writer.setBookList(new ArrayList<Book>());
}
EntityManager em = null;
try {
utx.begin();
em = getEntityManager();
List<Topic> attachedTopicList = new ArrayList<Topic>();
for (Topic topicListTopicToAttach : writer.getTopicList()) {
topicListTopicToAttach = em.getReference(topicListTopicToAttach.getClass(), topicListTopicToAttach.getTopicname());
attachedTopicList.add(topicListTopicToAttach);
}
writer.setTopicList(attachedTopicList);
List<Evaluation> attachedEvaluationList = new ArrayList<Evaluation>();
for (Evaluation evaluationListEvaluationToAttach : writer.getEvaluationList()) {
evaluationListEvaluationToAttach = em.getReference(evaluationListEvaluationToAttach.getClass(), evaluationListEvaluationToAttach.getEvaluationPK());
attachedEvaluationList.add(evaluationListEvaluationToAttach);
}
writer.setEvaluationList(attachedEvaluationList);
List<Book> attachedBookList = new ArrayList<Book>();
for (Book bookListBookToAttach : writer.getBookList()) {
bookListBookToAttach = em.getReference(bookListBookToAttach.getClass(), bookListBookToAttach.getBookPK());
attachedBookList.add(bookListBookToAttach);
}
writer.setBookList(attachedBookList);
em.persist(writer);
for (Topic topicListTopic : writer.getTopicList()) {
topicListTopic.getWriterList().add(writer);
topicListTopic = em.merge(topicListTopic);
}
for (Evaluation evaluationListEvaluation : writer.getEvaluationList()) {
Writer oldWriterOfEvaluationListEvaluation = evaluationListEvaluation.getWriter();
evaluationListEvaluation.setWriter(writer);
evaluationListEvaluation = em.merge(evaluationListEvaluation);
if (oldWriterOfEvaluationListEvaluation != null) {
oldWriterOfEvaluationListEvaluation.getEvaluationList().remove(evaluationListEvaluation);
oldWriterOfEvaluationListEvaluation = em.merge(oldWriterOfEvaluationListEvaluation);
}
}
for (Book bookListBook : writer.getBookList()) {
Writer oldWriterOfBookListBook = bookListBook.getWriter();
bookListBook.setWriter(writer);
bookListBook = em.merge(bookListBook);
if (oldWriterOfBookListBook != null) {
oldWriterOfBookListBook.getBookList().remove(bookListBook);
oldWriterOfBookListBook = em.merge(oldWriterOfBookListBook);
}
}
utx.commit();
} catch (Exception ex) {
try {
utx.rollback();
} catch (Exception re) {
throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
}
throw ex;
} finally {
if (em != null) {
em.close();
}
}
}
public void edit(Writer writer) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
// remainder of code goes here
}
public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
// remainder of code goes here
}
public List<Writer> findWriterEntities() {
return findWriterEntities(true, -1, -1);
}
public List<Writer> findWriterEntities(int maxResults, int firstResult) {
return findWriterEntities(false, maxResults, firstResult);
}
private List<Writer> findWriterEntities(boolean all, int maxResults, int firstResult) {
EntityManager em = getEntityManager();
try {
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
cq.select(cq.from(Writer.class));
Query q = em.createQuery(cq);
if (!all) {
q.setMaxResults(maxResults);
q.setFirstResult(firstResult);
}
return q.getResultList();
} finally {
em.close();
}
}
public Writer findWriter(Integer id) {
EntityManager em = getEntityManager();
try {
return em.find(Writer.class, id);
} finally {
em.close();
}
}
public int getWriterCount() {
EntityManager em = getEntityManager();
try {
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
Root<Writer> rt = cq.from(Writer.class);
cq.select(em.getCriteriaBuilder().count(rt));
Query q = em.createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
} finally {
em.close();
}
}
}
When I place a selectOneMenu within a dataTable, it does not display the correct default value in the selectOneMenu. The datatable is bound to a list of POJO's. The POJO entity Badge references a POJO entity we will call Facility. This Facility should be the selected value of the selectOneMenu in the row (the row being each Badge).
The following is my simple example of a table:
<h:dataTable id="examp" value="#{managedBean.badges}" var="badge">
<h:column rowHeader="rowie">
<h:selectOneMenu value="#{badge.facility}" id="col1">
<f:converter converterId="facilityConverter" />
<f:selectItems value="#{managedBean.facilities}"
/>
</h:selectOneMenu>
</h:column>
</h:dataTable>
The selectItems are a List of SelectItem objects that are created at PostConstruct. These are within my managedbean that is in ViewScope.
public class ListBadges extends BaseBean {
private List<Badge> badges = new ArrayList<Badge>();
private List<SelectItem> facilities = new ArrayList<SelectItem>();
public ListBadges() {
getBadgesFromDatabase(true);
}
#PostConstruct
public void init() {
if (facilities.size() <= 0) {
try {
List<Facility> facilityBeans = FacilityHelper.getFacilities();
for (Facility fac : facilityBeans) {
facilities.add(new SelectItem(fac, fac.getFacilityName()));
}
} catch (tException e) {
log.error("ListBadges.init(): " + e.getMessage());
e.printStackTrace();
}
}
}
public void getBadgesFromDatabase(boolean forceRefresh) {
if (forceRefresh || badges == null || badges.isEmpty())
badges = BadgeHelper.getBadgeList();
}
///
/// Bean Properties
///
public List<Badge> getBadges() {
return badges;
}
public void setBadges(List<Badge> badges) {
this.badges = badges;
}
public List<SelectItem> getFacilities() {
return facilities;
}
public void setFacilities(List<SelectItem> facilities) {
this.facilities = facilities;
}
Stepping through the code I confirm that all of the data is correct. In my converter, I verified that the arguments passed to getAsString is correct, so it should have identified the correct item.
#FacesConverter("facilityConverter")
public class FacilityConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String from) {
try {
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
ListBadges neededBean =
(ListBadges) context.getApplication().getELResolver().getValue(elContext, null, "managedBean");
long id = Long.parseLong(from);
for (SelectItem sItem : neededBean.getFacilities()) {
Facility facility = (Facility)sItem.getValue();
if (facility.getFacilityId() == id)
return facility;
}
} catch (Exception e) {
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
try {
Facility facility = (Facility)value;
return facility.getFacilityId() + "";
} catch (Exception e) {
}
return null;
}
}
Here is the Facility class which has equals and hashCode implemented:
public class Facility implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private long facilityId;
private String facilityName;
private String address1;
private String address2;
private String city;
private String state;
private String postalCode;
private String url;
private String phone;
private String siteManager;
public Facility() {
}
public Facility(String facilityName) {
this.facilityName = facilityName;
}
public Facility(String facilityName,
String address1, String address2, String city, String state,
String postalCode, String url, String phone, String siteManager) {
this.facilityName = facilityName;
this.address1 = address1;
this.address2 = address2;
this.city = city;
this.state = state;
this.postalCode = postalCode;
this.url = url;
this.phone = phone;
this.siteManager = siteManager;
}
public long getFacilityId() {
return this.facilityId;
}
public void setFacilityId(long facilityId) {
this.facilityId = facilityId;
}
public String getFacilityName() {
return this.facilityName;
}
public void setFacilityName(String facilityName) {
this.facilityName = facilityName;
}
public String getAddress1() {
return this.address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return this.address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public String getPostalCode() {
return this.postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSiteManager() {
return siteManager;
}
public void setSiteManager(String siteManager) {
this.siteManager = siteManager;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof Facility) || (o == null))
return false;
if (o == this)
return true;
Facility obj = (Facility)o;
return obj.getFacilityId() == this.getFacilityId();
}
#Override
public int hashCode() {
return (new Long(this.getFacilityId()).hashCode()) ^
((this.getAddress1() == null) ? 0 : this.getAddress1().hashCode()) ^
((this.getAddress2() == null) ? 0 : this.getAddress2().hashCode()) ^
((this.getCity() == null) ? 0 : this.getCity().hashCode()) ^
((this.getFacilityName() == null) ? 0 : this.getFacilityName().hashCode()) ^
((this.getPhone() == null) ? 0 : this.getPhone().hashCode()) ^
((this.getPostalCode() == null) ? 0 : this.getPostalCode().hashCode()) ^
((this.getSiteManager() == null) ? 0 : this.getSiteManager().hashCode()) ^
((this.getUrl() == null) ? 0 : this.getUrl().hashCode());
}
}
I would greatly appreciate any feedback.
I found the problem and it is nothing to do with JSF.
Eclipse was loading an older version of the Facility bean class that had a programmatic mistake in its equals method. Even after fully cleaning, republishing, cleaning the working directory, restarting the web server, and restarting Eclipse this old class was still getting loaded. I restarted my computer and finally the correct class was being loaded and this problem went away.
Thanks for looking at this BalusC. Without this blog article you wrote I would be completely lost! http://balusc.blogspot.com/2007/09/objects-in-hselectonemenu.html